diff options
Diffstat (limited to 'client/mysql.cc')
-rw-r--r-- | client/mysql.cc | 468 |
1 files changed, 243 insertions, 225 deletions
diff --git a/client/mysql.cc b/client/mysql.cc index 483b1829ec0..79d8ef0a35c 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -43,7 +43,7 @@ #include <locale.h> #endif -const char *VER= "14.12"; +const char *VER= "14.14"; /* Don't try to make a nice table if the data is too big */ #define MAX_COLUMN_LENGTH 1024 @@ -51,7 +51,10 @@ const char *VER= "14.12"; /* Buffer to hold 'version' and 'version_comment' */ #define MAX_SERVER_VERSION_LENGTH 128 -gptr sql_alloc(unsigned size); // Don't use mysqld alloc for these +/* Array of options to pass to libemysqld */ +#define MAX_SERVER_ARGS 64 + +void* sql_alloc(unsigned size); // Don't use mysqld alloc for these void sql_element_free(void *ptr); #include "sql_string.h" @@ -83,7 +86,7 @@ extern "C" { #endif #undef bcmp // Fix problem with new readline -#if defined( __WIN__) || defined(OS2) +#if defined( __WIN__) #include <conio.h> #elif !defined(__NETWARE__) #include <readline/readline.h> @@ -103,7 +106,7 @@ extern "C" { #define cmp_database(cs,A,B) strcmp((A),(B)) #endif -#if !defined( __WIN__) && !defined( OS2) && !defined(__NETWARE__) && (!defined(HAVE_mit_thread) || !defined(THREAD)) +#if !defined( __WIN__) && !defined(__NETWARE__) && !defined(THREAD) #define USE_POPEN #endif @@ -129,7 +132,7 @@ enum enum_info_type { INFO_INFO,INFO_ERROR,INFO_RESULT}; typedef enum enum_info_type INFO_TYPE; static MYSQL mysql; /* The connection */ -static my_bool info_flag=0,ignore_errors=0,wait_flag=0,quick=0, +static my_bool ignore_errors=0,wait_flag=0,quick=0, connected=0,opt_raw_data=0,unbuffered=0,output_tables=0, opt_rehash=1,skip_updates=0,safe_updates=0,one_database=0, opt_compress=0, using_opt_local_infile=0, @@ -138,12 +141,14 @@ static my_bool info_flag=0,ignore_errors=0,wait_flag=0,quick=0, tty_password= 0, opt_nobeep=0, opt_reconnect=1, default_charset_used= 0, opt_secure_auth= 0, default_pager_set= 0, opt_sigint_ignore= 0, - show_warnings= 0; -static volatile int executing_query= 0, interrupted_query= 0; + show_warnings= 0, executing_query= 0, interrupted_query= 0; +static my_bool debug_info_flag, debug_check_flag; +static my_bool column_types_flag; static my_bool preserve_comments= 0; static ulong opt_max_allowed_packet, opt_net_buffer_length; static uint verbose=0,opt_silent=0,opt_mysql_port=0, opt_local_infile=0; -static my_string opt_mysql_unix_port=0; +static uint my_end_arg; +static char * opt_mysql_unix_port=0; static int connect_flag=CLIENT_INTERACTIVE; static char *current_host,*current_db,*current_user=0,*opt_password=0, *current_prompt=0, *delimiter_str= 0, @@ -192,6 +197,8 @@ void tee_putc(int c, FILE *file); static void tee_print_sized_data(const char *, unsigned int, unsigned int, bool); /* The names of functions that actually do the manipulation. */ static int get_options(int argc,char **argv); +extern "C" my_bool get_one_option(int optid, const struct my_option *opt, + char *argument); static int com_quit(String *str,char*), com_go(String *str,char*), com_ego(String *str,char*), com_print(String *str,char*), @@ -1008,7 +1015,10 @@ static COMMANDS commands[] = { }; static const char *load_default_groups[]= { "mysql","client",0 }; -static const char *server_default_groups[]= + +static int embedded_server_arg_count= 0; +static char *embedded_server_args[MAX_SERVER_ARGS]; +static const char *embedded_server_groups[]= { "server", "embedded", "mysql_SERVER", 0 }; #ifdef HAVE_READLINE @@ -1047,22 +1057,12 @@ 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); -static sig_handler mysql_sigint(int sig); - +extern "C" sig_handler mysql_end(int sig); +extern "C" sig_handler handle_sigint(int sig); int main(int argc,char *argv[]) { char buff[80]; - char *defaults, *extra_defaults, *group_suffix; - char *emb_argv[4]; - int emb_argc; - - /* 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; MY_INIT(argv[0]); DBUG_ENTER("main"); @@ -1123,7 +1123,8 @@ int main(int argc,char *argv[]) my_end(0); exit(1); } - if (mysql_server_init(emb_argc, emb_argv, (char**) server_default_groups)) + if (mysql_server_init(embedded_server_arg_count, embedded_server_args, + (char**) embedded_server_groups)) { put_error(NULL); free_defaults(defaults_argv); @@ -1147,7 +1148,7 @@ int main(int argc,char *argv[]) if (opt_sigint_ignore) signal(SIGINT, SIG_IGN); else - signal(SIGINT, mysql_sigint); // Catch SIGINT to clean up + signal(SIGINT, handle_sigint); // Catch SIGINT to clean up signal(SIGQUIT, mysql_end); // Catch SIGQUIT to clean up put_info("Welcome to the MySQL monitor. Commands end with ; or \\g.", @@ -1211,28 +1212,6 @@ int main(int argc,char *argv[]) #endif } -sig_handler mysql_sigint(int sig) -{ - char kill_buffer[40]; - MYSQL *kill_mysql= NULL; - - signal(SIGINT, mysql_sigint); - - /* terminate if no query being executed, or we already tried interrupting */ - if (!executing_query || interrupted_query++) - mysql_end(sig); - - 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)) - mysql_end(sig); - /* kill_buffer is always big enough because max length of %lu is 15 */ - sprintf(kill_buffer, "KILL /*!50000 QUERY */ %lu", mysql_thread_id(&mysql)); - mysql_real_query(kill_mysql, kill_buffer, strlen(kill_buffer)); - mysql_close(kill_mysql); - tee_fprintf(stdout, "Query aborted by Ctrl+C\n"); -} - sig_handler mysql_end(int sig) { mysql_close(&mysql); @@ -1269,13 +1248,44 @@ sig_handler mysql_end(int sig) my_free(shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR)); #endif my_free(current_prompt,MYF(MY_ALLOW_ZERO_PTR)); + while (embedded_server_arg_count > 1) + my_free(embedded_server_args[--embedded_server_arg_count],MYF(0)); mysql_server_end(); free_defaults(defaults_argv); - my_end(info_flag ? MY_CHECK_ERROR | MY_GIVE_INFO : 0); + my_end(my_end_arg); exit(status.exit_status); } +/* + This function handles sigint calls + If query is in process, kill query + no query in process, terminate like previous behavior + */ +sig_handler handle_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) + mysql_end(sig); + + 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)) + mysql_end(sig); + + /* kill_buffer is always big enough because max length of %lu is 15 */ + sprintf(kill_buffer, "KILL /*!50000 QUERY */ %lu", mysql_thread_id(&mysql)); + mysql_real_query(kill_mysql, kill_buffer, strlen(kill_buffer)); + mysql_close(kill_mysql); + tee_fprintf(stdout, "Query aborted by Ctrl+C\n"); + + interrupted_query= 1; +} + + static struct my_option my_long_options[] = { {"help", '?', "Display this help and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, @@ -1288,7 +1298,7 @@ static struct my_option my_long_options[] = #endif {"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.", - (gptr*) &opt_rehash, (gptr*) &opt_rehash, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, + (uchar**) &opt_rehash, (uchar**) &opt_rehash, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, {"no-auto-rehash", 'A', "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.", @@ -1296,40 +1306,49 @@ static struct my_option my_long_options[] = {"batch", 'B', "Don't use history file. Disable interactive behavior. (Enables --silent)", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"character-sets-dir", OPT_CHARSETS_DIR, - "Directory where character sets are.", (gptr*) &charsets_dir, - (gptr*) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"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}, + "Directory where character sets are.", (uchar**) &charsets_dir, + (uchar**) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"column-type-info", OPT_COLUMN_TYPES, "Display column type information.", + (uchar**) &column_types_flag, (uchar**) &column_types_flag, + 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"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, + (uchar**) &preserve_comments, (uchar**) &preserve_comments, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"compress", 'C', "Use compression in server/client protocol.", - (gptr*) &opt_compress, (gptr*) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0, + (uchar**) &opt_compress, (uchar**) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + #ifdef DBUG_OFF {"debug", '#', "This is a non-debug version. Catch this and exit", 0,0, 0, GET_DISABLED, OPT_ARG, 0, 0, 0, 0, 0, 0}, #else - {"debug", '#', "Output debug log", (gptr*) &default_dbug_option, - (gptr*) &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, + {"debug", '#', "Output debug log", (uchar**) &default_dbug_option, + (uchar**) &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, #endif - {"database", 'D', "Database to use.", (gptr*) ¤t_db, - (gptr*) ¤t_db, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"delimiter", OPT_DELIMITER, "Delimiter to be used.", (gptr*) &delimiter_str, - (gptr*) &delimiter_str, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"debug-check", OPT_DEBUG_CHECK, "Check memory and open file usage at exit .", + (uchar**) &debug_check_flag, (uchar**) &debug_check_flag, 0, + GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"debug-info", 'T', "Print some debug info at exit.", (uchar**) &debug_info_flag, + (uchar**) &debug_info_flag, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"database", 'D', "Database to use.", (uchar**) ¤t_db, + (uchar**) ¤t_db, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"default-character-set", OPT_DEFAULT_CHARSET, + "Set the default character set.", (uchar**) &default_charset, + (uchar**) &default_charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"delimiter", OPT_DELIMITER, "Delimiter to be used.", (uchar**) &delimiter_str, + (uchar**) &delimiter_str, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"execute", 'e', "Execute command and quit. (Disables --force and history file)", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"vertical", 'E', "Print the output of a query (rows) vertically.", - (gptr*) &vertical, (gptr*) &vertical, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, + (uchar**) &vertical, (uchar**) &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, + (uchar**) &ignore_errors, (uchar**) &ignore_errors, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"named-commands", 'G', "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.", - (gptr*) &named_cmds, (gptr*) &named_cmds, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, + (uchar**) &named_cmds, (uchar**) &named_cmds, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"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.", @@ -1337,25 +1356,25 @@ static struct my_option my_long_options[] = {"ignore-spaces", 'i', "Ignore space after function names.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"local-infile", OPT_LOCAL_INFILE, "Enable/disable LOAD DATA LOCAL INFILE.", - (gptr*) &opt_local_infile, - (gptr*) &opt_local_infile, 0, GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0}, - {"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}, - {"host", 'h', "Connect to host.", (gptr*) ¤t_host, - (gptr*) ¤t_host, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"html", 'H', "Produce HTML output.", (gptr*) &opt_html, (gptr*) &opt_html, + (uchar**) &opt_local_infile, + (uchar**) &opt_local_infile, 0, GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0}, + {"no-beep", 'b', "Turn off beep on error.", (uchar**) &opt_nobeep, + (uchar**) &opt_nobeep, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"host", 'h', "Connect to host.", (uchar**) ¤t_host, + (uchar**) ¤t_host, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"html", 'H', "Produce HTML output.", (uchar**) &opt_html, (uchar**) &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, + {"xml", 'X', "Produce XML output", (uchar**) &opt_xml, (uchar**) &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, + (uchar**) &line_numbers, (uchar**) &line_numbers, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, {"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, 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}, + {"unbuffered", 'n', "Flush buffer after each query.", (uchar**) &unbuffered, + (uchar**) &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, + (uchar**) &column_names, (uchar**) &column_names, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, {"skip-column-names", 'N', "Don't write column names in results. WARNING: -N is deprecated, use long version of this options instead.", @@ -1364,7 +1383,7 @@ static struct my_option my_long_options[] = "Change the value of a variable. Please note that this option is deprecated; you can set variables directly with --variable-name=value.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"sigint-ignore", OPT_SIGINT_IGNORE, "Ignore SIGINT (CTRL-C)", - (gptr*) &opt_sigint_ignore, (gptr*) &opt_sigint_ignore, 0, GET_BOOL, + (uchar**) &opt_sigint_ignore, (uchar**) &opt_sigint_ignore, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"one-database", 'o', "Only update the default database. This is useful for skipping updates to other database in the update log.", @@ -1390,50 +1409,48 @@ static struct my_option my_long_options[] = "/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}, + (uchar**) &opt_mysql_port, + (uchar**) &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"prompt", OPT_PROMPT, "Set the mysql prompt to this value.", - (gptr*) ¤t_prompt, (gptr*) ¤t_prompt, 0, GET_STR_ALLOC, + (uchar**) ¤t_prompt, (uchar**) ¤t_prompt, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"protocol", OPT_MYSQL_PROTOCOL, "The protocol of connection (tcp,socket,pipe,memory).", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"quick", 'q', "Don't cache result, print it row by row. This may slow down the server if the output is suspended. Doesn't use history file.", - (gptr*) &quick, (gptr*) &quick, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + (uchar**) &quick, (uchar**) &quick, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"raw", 'r', "Write fields without conversion. Used with --batch.", - (gptr*) &opt_raw_data, (gptr*) &opt_raw_data, 0, GET_BOOL, NO_ARG, 0, 0, 0, + (uchar**) &opt_raw_data, (uchar**) &opt_raw_data, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"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}, + (uchar**) &opt_reconnect, (uchar**) &opt_reconnect, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, {"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, 0, 0}, #ifdef HAVE_SMEM {"shared-memory-base-name", OPT_SHARED_MEMORY_BASE_NAME, - "Base name of shared memory.", (gptr*) &shared_memory_base_name, (gptr*) &shared_memory_base_name, + "Base name of shared memory.", (uchar**) &shared_memory_base_name, (uchar**) &shared_memory_base_name, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #endif {"socket", 'S', "Socket file to use for connection.", - (gptr*) &opt_mysql_unix_port, (gptr*) &opt_mysql_unix_port, 0, GET_STR_ALLOC, + (uchar**) &opt_mysql_unix_port, (uchar**) &opt_mysql_unix_port, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #include "sslopt-longopts.h" - {"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}, + {"table", 't', "Output in table format.", (uchar**) &output_tables, + (uchar**) &output_tables, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"tee", OPT_TEE, "Append everything into outfile. See interactive help (\\h) also. Does not work in batch mode. Disable with --disable-tee. This option is disabled by default.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"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}, #ifndef DONT_ALLOW_USER_CHANGE - {"user", 'u', "User for login if not current user.", (gptr*) ¤t_user, - (gptr*) ¤t_user, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"user", 'u', "User for login if not current user.", (uchar**) ¤t_user, + (uchar**) ¤t_user, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #endif {"safe-updates", 'U', "Only allow UPDATE and DELETE that uses keys.", - (gptr*) &safe_updates, (gptr*) &safe_updates, 0, GET_BOOL, NO_ARG, 0, 0, + (uchar**) &safe_updates, (uchar**) &safe_updates, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"i-am-a-dummy", 'U', "Synonym for option --safe-updates, -U.", - (gptr*) &safe_updates, (gptr*) &safe_updates, 0, GET_BOOL, NO_ARG, 0, 0, + (uchar**) &safe_updates, (uchar**) &safe_updates, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"verbose", 'v', "Write more. (-v -v -v gives the table output format).", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, @@ -1443,33 +1460,35 @@ static struct my_option my_long_options[] = NO_ARG, 0, 0, 0, 0, 0, 0}, {"connect_timeout", OPT_CONNECT_TIMEOUT, "Number of seconds before connection timeout.", - (gptr*) &opt_connect_timeout, - (gptr*) &opt_connect_timeout, 0, GET_ULONG, REQUIRED_ARG, 0, 0, 3600*12, 0, - 0, 1}, + (uchar**) &opt_connect_timeout, + (uchar**) &opt_connect_timeout, 0, GET_ULONG, REQUIRED_ARG, 0, 0, 3600*12, 0, + 0, 0}, {"max_allowed_packet", OPT_MAX_ALLOWED_PACKET, "Max packet length to send to, or receive from server", - (gptr*) &opt_max_allowed_packet, (gptr*) &opt_max_allowed_packet, 0, + (uchar**) &opt_max_allowed_packet, (uchar**) &opt_max_allowed_packet, 0, GET_ULONG, REQUIRED_ARG, 16 *1024L*1024L, 4096, (longlong) 2*1024L*1024L*1024L, MALLOC_OVERHEAD, 1024, 0}, {"net_buffer_length", OPT_NET_BUFFER_LENGTH, "Buffer for TCP/IP and socket communication", - (gptr*) &opt_net_buffer_length, (gptr*) &opt_net_buffer_length, 0, GET_ULONG, + (uchar**) &opt_net_buffer_length, (uchar**) &opt_net_buffer_length, 0, GET_ULONG, REQUIRED_ARG, 16384, 1024, 512*1024*1024L, MALLOC_OVERHEAD, 1024, 0}, {"select_limit", OPT_SELECT_LIMIT, "Automatic limit for SELECT when using --safe-updates", - (gptr*) &select_limit, - (gptr*) &select_limit, 0, GET_ULONG, REQUIRED_ARG, 1000L, 1, ULONG_MAX, + (uchar**) &select_limit, + (uchar**) &select_limit, 0, GET_ULONG, REQUIRED_ARG, 1000L, 1, ULONG_MAX, 0, 1, 0}, {"max_join_size", OPT_MAX_JOIN_SIZE, "Automatic limit for rows in a join when using --safe-updates", - (gptr*) &max_join_size, - (gptr*) &max_join_size, 0, GET_ULONG, REQUIRED_ARG, 1000000L, 1, ULONG_MAX, + (uchar**) &max_join_size, + (uchar**) &max_join_size, 0, GET_ULONG, REQUIRED_ARG, 1000000L, 1, ULONG_MAX, 0, 1, 0}, {"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}, + " uses old (pre-4.1.1) protocol", (uchar**) &opt_secure_auth, + (uchar**) &opt_secure_auth, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"server-arg", OPT_SERVER_ARG, "Send embedded server this as a parameter.", + 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"show-warnings", OPT_SHOW_WARNINGS, "Show warnings after every statement.", - (gptr*) &show_warnings, (gptr*) &show_warnings, 0, GET_BOOL, NO_ARG, + (uchar**) &show_warnings, (uchar**) &show_warnings, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; @@ -1514,7 +1533,7 @@ and you are welcome to modify and redistribute it under the GPL license\n"); } -static my_bool +my_bool get_one_option(int optid, const struct my_option *opt __attribute__((unused)), char *argument) { @@ -1592,15 +1611,32 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), opt_nopager= 1; break; case OPT_MYSQL_PROTOCOL: - { - if ((opt_protocol= find_type(argument, &sql_protocol_typelib,0)) <= 0) + opt_protocol= find_type_or_exit(argument, &sql_protocol_typelib, + opt->name); + break; + case OPT_SERVER_ARG: +#ifdef EMBEDDED_LIBRARY + /* + When the embedded server is being tested, the client needs to be + able to pass command-line arguments to the embedded server so it can + locate the language files and data directory. + */ + if (!embedded_server_arg_count) { - fprintf(stderr, "Unknown option to protocol: %s\n", argument); - exit(1); + embedded_server_arg_count= 1; + embedded_server_args[0]= (char*) ""; + } + if (embedded_server_arg_count == MAX_SERVER_ARGS-1 || + !(embedded_server_args[embedded_server_arg_count++]= + my_strdup(argument, MYF(MY_FAE)))) + { + put_info("Can't use server argument", INFO_ERROR); + return 0; } +#else /*EMBEDDED_LIBRARY */ + printf("WARNING: --server-arg option not supported in this configuration.\n"); +#endif break; - } - break; case 'A': opt_rehash= 0; break; @@ -1639,7 +1675,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), break; case '#': DBUG_PUSH(argument ? argument : default_dbug_option); - info_flag= 1; + debug_info_flag= 1; break; case 's': if (argument == disabled_my_option) @@ -1733,12 +1769,16 @@ static int get_options(int argc, char **argv) } if (tty_password) opt_password= get_tty_password(NullS); + if (debug_info_flag) + my_end_arg= MY_CHECK_ERROR | MY_GIVE_INFO; + if (debug_check_flag) + my_end_arg= MY_CHECK_ERROR; return(0); } static int read_and_execute(bool interactive) { -#if defined(OS2) || defined(__NETWARE__) +#if defined(__NETWARE__) char linebuffer[254]; String buffer; #endif @@ -1786,9 +1826,7 @@ static int read_and_execute(bool interactive) if (opt_outfile && glob_buffer.is_empty()) fflush(OUTFILE); - interrupted_query= 0; - -#if defined( __WIN__) || defined(OS2) || defined(__NETWARE__) +#if defined( __WIN__) || defined(__NETWARE__) tee_fputs(prompt, stdout); #if defined(__NETWARE__) line=fgets(linebuffer, sizeof(linebuffer)-1, stdin); @@ -1799,12 +1837,12 @@ static int read_and_execute(bool interactive) if (p != NULL) *p = '\0'; } -#elif defined(__WIN__) +#else defined(__WIN__) if (!tmpbuf.is_alloced()) tmpbuf.alloc(65535); tmpbuf.length(0); buffer.length(0); - unsigned long clen; + size_t clen; do { line= my_cgets((char*)tmpbuf.ptr(), tmpbuf.alloced_length()-1, &clen); @@ -1820,32 +1858,12 @@ static int read_and_execute(bool interactive) */ if (line) line= buffer.c_ptr(); -#else /* OS2 */ - buffer.length(0); - /* _cgets() expects the buffer size - 3 as the first byte */ - linebuffer[0]= (char) sizeof(linebuffer) - 3; - 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. - */ - } while ((unsigned char)linebuffer[0] <= - (unsigned char)linebuffer[1] + 1); - line= buffer.c_ptr(); #endif /* __NETWARE__ */ #else if (opt_outfile) fputs(prompt, OUTFILE); line= readline(prompt); -#endif /* defined( __WIN__) || defined(OS2) || defined(__NETWARE__) */ +#endif /* defined( __WIN__) || defined(__NETWARE__) */ /* When Ctrl+d or Ctrl+z is pressed, the line may be NULL on some OS @@ -1893,7 +1911,7 @@ static int read_and_execute(bool interactive) } } -#if defined( __WIN__) || defined(OS2) || defined(__NETWARE__) +#if defined( __WIN__) || defined(__NETWARE__) buffer.free(); #endif #if defined( __WIN__) @@ -2233,7 +2251,7 @@ static bool add_line(String &buffer,char *line,char *in_string, #ifdef HAVE_READLINE static char *new_command_generator(const char *text, int); -static char **new_mysql_completion (const char *text, int start, int end); +extern "C" char **new_mysql_completion (const char *text, int start, int end); /* Tell the GNU Readline library how to complete. We want to try to complete @@ -2242,9 +2260,9 @@ static char **new_mysql_completion (const char *text, int start, int end); */ #if defined(USE_NEW_READLINE_INTERFACE) || defined(USE_LIBEDIT_INTERFACE) -char *no_completion(const char*,int) +extern "C" char *no_completion(const char*,int) #else -char *no_completion() +extern "C" char *no_completion() #endif { return 0; /* No filename completion */ @@ -2346,9 +2364,9 @@ static void initialize_readline (char *name) array of matches, or NULL if there aren't any. */ -static char **new_mysql_completion (const char *text, - int start __attribute__((unused)), - int end __attribute__((unused))) +char **new_mysql_completion (const char *text, + int start __attribute__((unused)), + int end __attribute__((unused))) { if (!status.batch && !quick) #if defined(USE_NEW_READLINE_INTERFACE) @@ -2854,10 +2872,11 @@ com_go(String *buffer,char *line __attribute__((unused))) char buff[200]; /* about 110 chars used so far */ char time_buff[52+3+1]; /* time max + space&parens + NUL */ MYSQL_RES *result; - ulong timer, warnings; + ulong timer, warnings= 0; uint error= 0; int err= 0; + interrupted_query= 0; if (!status.batch) { old_buffer= *buffer; // Save for edit command @@ -2893,9 +2912,7 @@ com_go(String *buffer,char *line __attribute__((unused))) } timer=start_timer(); - executing_query= 1; - error= mysql_real_query_for_lazy(buffer->ptr(),buffer->length()); #ifdef HAVE_READLINE @@ -2907,15 +2924,11 @@ com_go(String *buffer,char *line __attribute__((unused))) } #endif - if (error) - { - buffer->length(0); // Remove query on error - executing_query= 0; - return error; - } - error=0; buffer->length(0); + if (error) + goto end; + do { char *pos; @@ -2924,18 +2937,15 @@ com_go(String *buffer,char *line __attribute__((unused))) { if (!(result=mysql_use_result(&mysql)) && mysql_field_count(&mysql)) { - executing_query= 0; - return put_error(&mysql); + error= put_error(&mysql); + goto end; } } else { error= mysql_store_result_for_lazy(&result); if (error) - { - executing_query= 0; - return error; - } + goto end; } if (verbose >= 3 || !opt_silent) @@ -2946,7 +2956,7 @@ com_go(String *buffer,char *line __attribute__((unused))) /* Every branch must truncate buff . */ if (result) { - if (!mysql_num_rows(result) && ! quick && !info_flag) + if (!mysql_num_rows(result) && ! quick && !column_types_flag) { strmov(buff, "Empty set"); if (opt_xml) @@ -3011,23 +3021,20 @@ com_go(String *buffer,char *line __attribute__((unused))) fflush(stdout); mysql_free_result(result); } while (!(err= mysql_next_result(&mysql))); - - executing_query= 0; - if (err >= 1) error= put_error(&mysql); - if (show_warnings == 1 && warnings >= 1) /* Show warnings if any */ - { - init_pager(); +end: + + /* Show warnings if any or error occured */ + if (show_warnings == 1 && (warnings >= 1 || error)) print_warnings(); - end_pager(); - } if (!error && !status.batch && (mysql.server_status & SERVER_STATUS_DB_DROPPED)) get_current_db(); + executing_query= 0; return error; /* New command follows */ } @@ -3099,32 +3106,32 @@ com_ego(String *buffer,char *line) static const char *fieldtype2str(enum enum_field_types type) { switch (type) { - 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"; + case MYSQL_TYPE_BIT: return "BIT"; + case MYSQL_TYPE_BLOB: return "BLOB"; + case MYSQL_TYPE_DATE: return "DATE"; + case MYSQL_TYPE_DATETIME: return "DATETIME"; + case MYSQL_TYPE_NEWDECIMAL: return "NEWDECIMAL"; + case MYSQL_TYPE_DECIMAL: return "DECIMAL"; + case MYSQL_TYPE_DOUBLE: return "DOUBLE"; + case MYSQL_TYPE_ENUM: return "ENUM"; + case MYSQL_TYPE_FLOAT: return "FLOAT"; + case MYSQL_TYPE_GEOMETRY: return "GEOMETRY"; + case MYSQL_TYPE_INT24: return "INT24"; + case MYSQL_TYPE_LONG: return "LONG"; + case MYSQL_TYPE_LONGLONG: return "LONGLONG"; + case MYSQL_TYPE_LONG_BLOB: return "LONG_BLOB"; + case MYSQL_TYPE_MEDIUM_BLOB: return "MEDIUM_BLOB"; + case MYSQL_TYPE_NEWDATE: return "NEWDATE"; + case MYSQL_TYPE_NULL: return "NULL"; + case MYSQL_TYPE_SET: return "SET"; + case MYSQL_TYPE_SHORT: return "SHORT"; + case MYSQL_TYPE_STRING: return "STRING"; + case MYSQL_TYPE_TIME: return "TIME"; + case MYSQL_TYPE_TIMESTAMP: return "TIMESTAMP"; + case MYSQL_TYPE_TINY: return "TINY"; + case MYSQL_TYPE_TINY_BLOB: return "TINY_BLOB"; + case MYSQL_TYPE_VAR_STRING: return "VAR_STRING"; + case MYSQL_TYPE_YEAR: return "YEAR"; default: return "?-unknown-?"; } } @@ -3153,6 +3160,7 @@ static char *fieldflags2str(uint f) { ff2s_check_flag(GROUP); ff2s_check_flag(UNIQUE); ff2s_check_flag(BINCMP); + ff2s_check_flag(ON_UPDATE_NOW); #undef ff2s_check_flag if (f) sprintf(s, " unknows=0x%04x", f); @@ -3198,7 +3206,7 @@ print_table_data(MYSQL_RES *result) bool *num_flag; num_flag=(bool*) my_alloca(sizeof(bool)*mysql_num_fields(result)); - if (info_flag) + if (column_types_flag) { print_field_types(result); if (!mysql_num_rows(result)) @@ -3243,6 +3251,8 @@ print_table_data(MYSQL_RES *result) while ((cur= mysql_fetch_row(result))) { + if (interrupted_query) + break; ulong *lengths= mysql_fetch_lengths(result); (void) tee_fputs("| ", PAGER); mysql_field_seek(result, 0); @@ -3254,7 +3264,6 @@ print_table_data(MYSQL_RES *result) uint visible_length; uint extra_padding; - /* If this column may have a null value, use "NULL" for empty. */ if (cur[off] == NULL) { buffer= "NULL"; @@ -3294,7 +3303,7 @@ print_table_data(MYSQL_RES *result) (void) tee_fputs("\n", PAGER); } tee_puts((char*) separator.ptr(), PAGER); - my_afree((gptr) num_flag); + my_afree((uchar*) num_flag); } @@ -3348,6 +3357,8 @@ print_table_data_html(MYSQL_RES *result) } while ((cur = mysql_fetch_row(result))) { + if (interrupted_query) + break; ulong *lengths=mysql_fetch_lengths(result); (void) tee_fputs("<TR>", PAGER); for (uint i=0; i < mysql_num_fields(result); i++) @@ -3378,6 +3389,8 @@ print_table_data_xml(MYSQL_RES *result) fields = mysql_fetch_fields(result); while ((cur = mysql_fetch_row(result))) { + if (interrupted_query) + break; ulong *lengths=mysql_fetch_lengths(result); (void) tee_fputs("\n <row>\n", PAGER); for (uint i=0; i < mysql_num_fields(result); i++) @@ -3417,6 +3430,8 @@ print_table_data_vertically(MYSQL_RES *result) mysql_field_seek(result,0); for (uint row_count=1; (cur= mysql_fetch_row(result)); row_count++) { + if (interrupted_query) + break; mysql_field_seek(result,0); tee_fprintf(PAGER, "*************************** %d. row ***************************\n", row_count); @@ -3438,6 +3453,9 @@ static void print_warnings() MYSQL_RES *result; MYSQL_ROW cur; my_ulonglong num_rows; + + /* Save current error before calling "show warnings" */ + uint error= mysql_errno(&mysql); /* Get the warnings */ query= "show warnings"; @@ -3446,16 +3464,28 @@ static void print_warnings() /* Bail out when no warnings */ if (!(num_rows= mysql_num_rows(result))) - { - mysql_free_result(result); - return; - } + goto end; + + cur= mysql_fetch_row(result); + + /* + Don't print a duplicate of the current error. It is possible for SHOW + WARNINGS to return multiple errors with the same code, but different + messages. To be safe, skip printing the duplicate only if it is the only + warning. + */ + if (!cur || num_rows == 1 && error == (uint) strtoul(cur[1], NULL, 10)) + goto end; /* Print the warnings */ - while ((cur= mysql_fetch_row(result))) + init_pager(); + do { tee_fprintf(PAGER, "%s (Code %s): %s\n", cur[0], cur[1], cur[2]); - } + } while ((cur= mysql_fetch_row(result))); + end_pager(); + +end: mysql_free_result(result); } @@ -3687,10 +3717,10 @@ com_edit(String *buffer,char *line __attribute__((unused))) MYF(MY_WME))) < 0) goto err; if (buffer->is_empty() && !old_buffer.is_empty()) - (void) my_write(fd,(byte*) old_buffer.ptr(),old_buffer.length(), + (void) my_write(fd,(uchar*) old_buffer.ptr(),old_buffer.length(), MYF(MY_WME)); else - (void) my_write(fd,(byte*) buffer->ptr(),buffer->length(),MYF(MY_WME)); + (void) my_write(fd,(uchar*) buffer->ptr(),buffer->length(),MYF(MY_WME)); (void) my_close(fd,MYF(0)); if (!(editor = (char *)getenv("EDITOR")) && @@ -4131,7 +4161,7 @@ sql_real_connect(char *host,char *database,char *user,char *password, } connected=1; #ifndef EMBEDDED_LIBRARY - mysql.reconnect=info_flag ? 1 : 0; // We want to know if this happens + mysql.reconnect= debug_info_flag; // We want to know if this happens #else mysql.reconnect= 1; #endif @@ -4430,9 +4460,6 @@ void tee_fprintf(FILE *file, const char *fmt, ...) NETWARE_YIELD; va_start(args, fmt); (void) vfprintf(file, fmt, args); -#ifdef OS2 - fflush( file); -#endif va_end(args); if (opt_outfile) @@ -4448,9 +4475,6 @@ void tee_fputs(const char *s, FILE *file) { NETWARE_YIELD; fputs(s, file); -#ifdef OS2 - fflush( file); -#endif if (opt_outfile) fputs(s, OUTFILE); } @@ -4461,9 +4485,6 @@ void tee_puts(const char *s, FILE *file) NETWARE_YIELD; fputs(s, file); fputc('\n', file); -#ifdef OS2 - fflush(file); -#endif if (opt_outfile) { fputs(s, OUTFILE); @@ -4474,14 +4495,11 @@ void tee_puts(const char *s, FILE *file) void tee_putc(int c, FILE *file) { putc(c, file); -#ifdef OS2 - fflush( file); -#endif if (opt_outfile) putc(c, OUTFILE); } -#if defined( __WIN__) || defined( OS2) || defined(__NETWARE__) +#if defined( __WIN__) || defined(__NETWARE__) #include <time.h> #else #include <sys/times.h> @@ -4493,7 +4511,7 @@ void tee_putc(int c, FILE *file) static ulong start_timer(void) { -#if defined( __WIN__) || defined( OS2) || defined(__NETWARE__) +#if defined( __WIN__) || defined(__NETWARE__) return clock(); #else struct tms tms_tmp; @@ -4758,13 +4776,13 @@ static int com_prompt(String *buffer, char *line) #ifndef EMBEDDED_LIBRARY /* Keep sql_string library happy */ -gptr sql_alloc(unsigned int Size) +void *sql_alloc(size_t Size) { return my_malloc(Size,MYF(MY_WME)); } void sql_element_free(void *ptr) { - my_free((gptr) ptr,MYF(0)); + my_free(ptr,MYF(0)); } #endif /* EMBEDDED_LIBRARY */ |