summaryrefslogtreecommitdiff
path: root/client/mysql.cc
diff options
context:
space:
mode:
Diffstat (limited to 'client/mysql.cc')
-rw-r--r--client/mysql.cc1471
1 files changed, 902 insertions, 569 deletions
diff --git a/client/mysql.cc b/client/mysql.cc
index 32547a4d138..da52fb54e7d 100644
--- a/client/mysql.cc
+++ b/client/mysql.cc
@@ -1,15 +1,15 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+/* Copyright (C) 2000-2003 MySQL AB
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -20,21 +20,27 @@
* Written by:
* Michael 'Monty' Widenius
* Andi Gutmans <andi@zend.com>
- * Zeev Suraski <zeev@zend.com>
- * Jani Tolonen <jani@mysql.com>
+ * Zeev Suraski <zeev@zend.com>
+ * Jani Tolonen <jani@mysql.com>
+ * Matt Wagner <matt@mysql.com>
+ * Jeremy Cole <jcole@mysql.com>
+ * Tonu Samuel <tonu@mysql.com>
+ * Harrison Fisk <hcfisk@buffalo.edu>
*
**/
#include "client_priv.h"
#include <m_ctype.h>
+#include <stdarg.h>
#include <my_dir.h>
#ifndef __GNU_LIBRARY__
#define __GNU_LIBRARY__ // Skip warnings in getopt.h
#endif
#include "my_readline.h"
#include <signal.h>
+#include <violite.h>
-const char *VER="11.18";
+const char *VER= "12.18";
/* Don't try to make a nice table if the data is too big */
#define MAX_COLUMN_LENGTH 1024
@@ -71,10 +77,9 @@ extern "C" {
#endif
#undef bcmp // Fix problem with new readline
-#undef bzero
#if defined( __WIN__) || defined(OS2)
#include <conio.h>
-#else
+#elif !defined(__NETWARE__)
#include <readline/readline.h>
#define HAVE_READLINE
#endif
@@ -86,14 +91,20 @@ extern "C" {
#define vidattr(A) {} // Can't get this to work
#endif
-#ifdef __WIN__
+#ifdef FN_NO_CASE_SENCE
#define cmp_database(A,B) my_strcasecmp((A),(B))
#else
#define cmp_database(A,B) strcmp((A),(B))
#endif
+#if !defined( __WIN__) && !defined( OS2) && !defined(__NETWARE__) && (!defined(HAVE_mit_thread) || !defined(THREAD))
+#define USE_POPEN
+#endif
+
#include "completion_hash.h"
+#define PROMPT_CHAR '\\'
+
typedef struct st_status
{
int exit_status;
@@ -105,30 +116,45 @@ typedef struct st_status
static HashTable ht;
+static char **defaults_argv;
enum enum_info_type { INFO_INFO,INFO_ERROR,INFO_RESULT};
typedef enum enum_info_type INFO_TYPE;
static MYSQL mysql; /* The connection */
-static bool info_flag=0,ignore_errors=0,wait_flag=0,quick=0,
- connected=0,opt_raw_data=0,unbuffered=0,output_tables=0,
- no_rehash=0,skip_updates=0,safe_updates=0,one_database=0,
- opt_compress=0, using_opt_local_infile=0,
- vertical=0,skip_line_numbers=0,skip_column_names=0,opt_html=0,
- opt_nopager=1, opt_outfile=0, no_named_cmds=1;
+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,
+ rehash=1,skip_updates=0,safe_updates=0,one_database=0,
+ opt_compress=0, using_opt_local_infile=0,
+ vertical=0, line_numbers=1, column_names=1,opt_html=0,
+ opt_xml=0,opt_nopager=1, opt_outfile=0, named_cmds= 0,
+ tty_password= 0, opt_nobeep=0;
static uint verbose=0,opt_silent=0,opt_mysql_port=0, opt_local_infile=0;
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,
- *default_charset;
+ *current_prompt=0, *default_charset;
static char *histfile;
static String glob_buffer,old_buffer;
+static String processed_prompt;
+static char *full_username=0,*part_username=0,*default_prompt=0;
static int wait_time = 5;
static STATUS status;
static ulong select_limit,max_join_size,opt_connect_timeout=0;
+static char mysql_charsets_dir[FN_REFLEN+1];
+static const char *xmlmeta[] = {
+ "&", "&amp;",
+ "<", "&lt;",
+ 0, 0
+};
+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];
-char pager[FN_REFLEN], outfile[FN_REFLEN];
-FILE *PAGER, *OUTFILE;
+static char pager[FN_REFLEN], outfile[FN_REFLEN];
+static FILE *PAGER, *OUTFILE;
+static MEM_ROOT hash_mem_root;
+static uint prompt_counter;
#include "sslopt-vars.h"
@@ -149,11 +175,12 @@ static int com_quit(String *str,char*),
com_connect(String *str,char*), com_status(String *str,char*),
com_use(String *str,char*), com_source(String *str, char*),
com_rehash(String *str, char*), com_tee(String *str, char*),
- com_notee(String *str, char*);
+ com_notee(String *str, char*),
+ com_prompt(String *str, char*);
-#ifndef __WIN__
+#ifdef USE_POPEN
static int com_nopager(String *str, char*), com_pager(String *str, char*),
- com_edit(String *str,char*);
+ com_edit(String *str,char*), com_shell(String *str, char *);
#endif
static int read_lines(bool execute_commands);
@@ -161,10 +188,14 @@ static int sql_connect(char *host,char *database,char *user,char *password,
uint silent);
static int put_info(const char *str,INFO_TYPE info,uint error=0);
static void safe_put_field(const char *pos,ulong length);
+static void xmlencode_print(const char *src, uint length);
static void init_pager();
static void end_pager();
-static void init_tee();
+static void init_tee(const char *);
static void end_tee();
+static const char* construct_prompt();
+static void init_username();
+static void add_int_to_prompt(int toadd);
/* A structure which contains information on the commands this program
can understand. */
@@ -183,27 +214,31 @@ static COMMANDS commands[] = {
{ "clear", 'c', com_clear, 0, "Clear command."},
{ "connect",'r', com_connect,1,
"Reconnect to the server. Optional arguments are db and host." },
-#ifndef __WIN__
+#ifdef USE_POPEN
{ "edit", 'e', com_edit, 0, "Edit command with $EDITOR."},
#endif
{ "ego", 'G', com_ego, 0,
"Send command to mysql server, display result vertically."},
{ "exit", 'q', com_quit, 0, "Exit mysql. Same as quit."},
{ "go", 'g', com_go, 0, "Send command to mysql server." },
-#ifndef __WIN__
+#ifdef USE_POPEN
{ "nopager",'n', com_nopager,0, "Disable pager, print to stdout." },
#endif
{ "notee", 't', com_notee, 0, "Don't write into outfile." },
-#ifndef __WIN__
+#ifdef USE_POPEN
{ "pager", 'P', com_pager, 1,
"Set PAGER [to_pager]. Print the query results via PAGER." },
#endif
{ "print", 'p', com_print, 0, "Print current command." },
+ { "prompt", 'R', com_prompt, 1, "Change your mysql prompt."},
{ "quit", 'q', com_quit, 0, "Quit mysql." },
{ "rehash", '#', com_rehash, 0, "Rebuild completion hash." },
{ "source", '.', com_source, 1,
"Execute a SQL script file. Takes a file name as an argument."},
{ "status", 's', com_status, 0, "Get status information from the server."},
+#ifdef USE_POPEN
+ { "system", '!', com_shell, 1, "Execute a system shell command."},
+#endif
{ "tee", 'T', com_tee, 1,
"Set outfile [to_outfile]. Append everything into given outfile." },
{ "use", 'u', com_use, 1,
@@ -232,6 +267,8 @@ static COMMANDS commands[] = {
};
static const char *load_default_groups[]= { "mysql","client",0 };
+static const char *server_default_groups[]=
+{ "server", "embedded", "mysql_SERVER", 0 };
#ifdef HAVE_READLINE
extern "C" void add_history(char *command); /* From readline directory */
@@ -245,6 +282,7 @@ static bool add_line(String &buffer,char *line,char *in_string);
static void remove_cntrl(String &buffer);
static void print_table_data(MYSQL_RES *result);
static void print_table_data_html(MYSQL_RES *result);
+static void print_table_data_xml(MYSQL_RES *result);
static void print_tab_data(MYSQL_RES *result);
static void print_table_data_vertically(MYSQL_RES *result);
static ulong start_timer(void);
@@ -262,8 +300,14 @@ int main(int argc,char *argv[])
DBUG_ENTER("main");
DBUG_PROCESS(argv[0]);
- strmov(outfile, "\0"); // no (default) outfile, unless given at least once
- strmov(pager, "stdout"); // the default, if --pager wasn't given
+ 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;
+
+ outfile[0]=0; // no (default) outfile
+ strmov(pager, "stdout"); // the default, if --pager wasn't given
{
char *tmp=getenv("PAGER");
if (tmp)
@@ -278,17 +322,24 @@ int main(int argc,char *argv[])
status.add_to_history=1;
status.exit_status=1;
load_defaults("my",load_default_groups,&argc,&argv);
- if (get_options(argc,(char **) argv))
+ defaults_argv=argv;
+ if (get_options(argc, (char **) argv))
{
+ free_defaults(defaults_argv);
my_end(0);
exit(1);
}
- free_defaults(argv);
if (status.batch && !status.line_buff &&
!(status.line_buff=batch_readline_init(max_allowed_packet+512,stdin)))
+ {
+ free_defaults(defaults_argv);
exit(1);
+ }
glob_buffer.realloc(512);
- completion_hash_init(&ht,50);
+ mysql_server_init(0, NULL, (char**) server_default_groups);
+ completion_hash_init(&ht, 128);
+ init_alloc_root(&hash_mem_root, 16384, 0);
+ bzero((char*) &mysql, sizeof(mysql));
if (sql_connect(current_host,current_db,current_user,opt_password,
opt_silent))
{
@@ -301,7 +352,7 @@ int main(int argc,char *argv[])
signal(SIGINT, mysql_end); // Catch SIGINT to clean up
/*
- ** Run in interactive mode like the ingres/postgres monitor
+ Run in interactive mode like the ingres/postgres monitor
*/
put_info("Welcome to the MySQL monitor. Commands end with ; or \\g.",
@@ -313,9 +364,9 @@ int main(int argc,char *argv[])
#ifdef HAVE_READLINE
initialize_readline(my_progname);
- if (!status.batch && !quick && !opt_html)
+ if (!status.batch && !quick && !opt_html && !opt_xml)
{
- /*read-history from file, default ~/.mysql_history*/
+ /* read-history from file, default ~/.mysql_history*/
if (getenv("MYSQL_HISTFILE"))
histfile=my_strdup(getenv("MYSQL_HISTFILE"),MYF(MY_WME));
else if (getenv("HOME"))
@@ -348,10 +399,9 @@ int main(int argc,char *argv[])
sig_handler mysql_end(int sig)
{
- if (connected)
- mysql_close(&mysql);
+ mysql_close(&mysql);
#ifdef HAVE_READLINE
- if (!status.batch && !quick && ! opt_html)
+ if (!status.batch && !quick && !opt_html && !opt_xml)
{
/* write-history */
if (verbose)
@@ -360,88 +410,181 @@ sig_handler mysql_end(int sig)
}
batch_readline_end(status.line_buff);
completion_hash_free(&ht);
+ free_root(&hash_mem_root,MYF(0));
+
#endif
if (sig >= 0)
put_info(sig ? "Aborted" : "Bye", INFO_RESULT);
glob_buffer.free();
old_buffer.free();
+ processed_prompt.free();
my_free(opt_password,MYF(MY_ALLOW_ZERO_PTR));
my_free(opt_mysql_unix_port,MYF(MY_ALLOW_ZERO_PTR));
my_free(histfile,MYF(MY_ALLOW_ZERO_PTR));
my_free(current_db,MYF(MY_ALLOW_ZERO_PTR));
my_free(current_host,MYF(MY_ALLOW_ZERO_PTR));
my_free(current_user,MYF(MY_ALLOW_ZERO_PTR));
+ 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));
+ my_free(current_prompt,MYF(MY_ALLOW_ZERO_PTR));
+ mysql_server_end();
+ free_defaults(defaults_argv);
my_end(info_flag ? MY_CHECK_ERROR | MY_GIVE_INFO : 0);
exit(status.exit_status);
}
-static struct option long_options[] =
+
+static struct my_option my_long_options[] =
{
- {"i-am-a-dummy", optional_argument, 0, 'U'},
- {"batch", no_argument, 0, 'B'},
- {"character-sets-dir",required_argument, 0, OPT_CHARSETS_DIR},
- {"compress", no_argument, 0, 'C'},
+ {"help", '?', "Display this help and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0,
+ 0, 0, 0, 0, 0},
+ {"auto-rehash", OPT_AUTO_REHASH,
+ "Enable automatic rehashing. One doesn't need to use 'rehash' to get table and field completion, but startup and reconnecting may take a longer time. Disable with --disable-auto-rehash.",
+ (gptr*) &rehash, (gptr*) &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.",
+ 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"batch", 'B',
+ "Print results with a tab as separator, each row on new line. Doesn't use history file.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"character-sets-dir", OPT_CHARSETS_DIR,
+ "Directory where character sets are.", (gptr*) &charsets_dir,
+ (gptr*) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"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},
+ {"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},
#ifndef DBUG_OFF
- {"debug", optional_argument, 0, '#'},
+ {"debug", '#', "Output debug log.", (gptr*) &default_dbug_option,
+ (gptr*) &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
#endif
- {"database", required_argument, 0, 'D'},
- {"debug-info", no_argument, 0, 'T'},
- {"default-character-set", required_argument,0, OPT_DEFAULT_CHARSET},
- {"enable-named-commands", no_argument, 0, 'G'},
- {"execute", required_argument, 0, 'e'},
- {"force", no_argument, 0, 'f'},
- {"help", no_argument, 0, '?'},
- {"html", no_argument, 0, 'H'},
- {"host", required_argument, 0, 'h'},
- {"ignore-spaces", no_argument, 0, 'i'},
- {"local-infile", optional_argument, 0, OPT_LOCAL_INFILE},
- {"no-auto-rehash",no_argument, 0, 'A'},
- {"no-named-commands", no_argument, 0, 'g'},
-#ifndef __WIN__
- {"no-pager", no_argument, 0, OPT_NOPAGER},
- {"nopager", no_argument, 0, OPT_NOPAGER}, /* we are kind */
- {"pager", optional_argument, 0, OPT_PAGER},
+ {"database", 'D', "Database to use.", (gptr*) &current_db,
+ (gptr*) &current_db, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"execute", 'e', "Execute command and quit. (Output like with --batch).", 0,
+ 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"vertical", 'E', "Print the output of a query (rows) vertically.",
+ (gptr*) &vertical, (gptr*) &vertical, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0,
+ 0},
+ {"force", 'f', "Continue even if we get an sql error.",
+ (gptr*) &ignore_errors, (gptr*) &ignore_errors, 0, GET_BOOL, NO_ARG, 0, 0,
+ 0, 0, 0, 0},
+ {"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},
+ {"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,
+ 0, 0},
+ {"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*) &current_host,
+ (gptr*) &current_host, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"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,
+ 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},
+#ifdef USE_POPEN
+ {"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},
#endif
- {"no-tee", no_argument, 0, OPT_NOTEE},
- {"notee", no_argument, 0, OPT_NOTEE}, /* we are kind */
- {"tee", required_argument, 0, OPT_TEE},
- {"one-database", no_argument, 0, 'o'},
- {"password", optional_argument, 0, 'p'},
+ {"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},
+ {"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,
+ 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.",
+ 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"set-variable", 'O',
+ "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},
+ {"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},
+#ifdef USE_POPEN
+ {"pager", OPT_PAGER,
+ "Pager to use to display results. If you don't supply an option the default pager is taken from your ENV variable PAGER. Valid pagers are less, more, cat [> filename], etc. See interactive help (\\h) also. This option does not work in batch mode.",
+ 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
+#endif
+ {"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},
#ifdef __WIN__
- {"pipe", no_argument, 0, 'W'},
+ {"pipe", 'W', "Use named pipes to connect to server.", 0, 0, 0, GET_NO_ARG,
+ NO_ARG, 0, 0, 0, 0, 0, 0},
#endif
- {"port", required_argument, 0, 'P'},
- {"quick", no_argument, 0, 'q'},
- {"set-variable", required_argument, 0, 'O'},
- {"raw", no_argument, 0, 'r'},
- {"safe-updates", optional_argument, 0, 'U'},
- {"silent", no_argument, 0, 's'},
- {"skip-column-names",no_argument, 0, 'N'},
- {"skip-line-numbers",no_argument, 0, 'L'},
- {"socket", required_argument, 0, 'S'},
+ {"port", 'P', "Port number to use for connection.", (gptr*) &opt_mysql_port,
+ (gptr*) &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, MYSQL_PORT, 0, 0, 0, 0,
+ 0},
+ {"prompt", OPT_PROMPT, "Set the mysql prompt to this value.",
+ (gptr*) &current_prompt, (gptr*) &current_prompt, 0, GET_STR_ALLOC,
+ 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},
+ {"raw", 'r', "Write fields without conversion. Used with --batch",
+ (gptr*) &opt_raw_data, (gptr*) &opt_raw_data, 0, GET_BOOL, NO_ARG, 0, 0, 0,
+ 0, 0, 0},
+ {"silent", 's', "Be more silent.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0,
+ 0, 0},
+ {"socket", 'S', "Socket file to use for connection.",
+ (gptr*) &opt_mysql_unix_port, (gptr*) &opt_mysql_unix_port, 0, GET_STR_ALLOC,
+ REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
#include "sslopt-longopts.h"
- {"table", no_argument, 0, 't'},
+ {"table", 't', "Output in table format.", (gptr*) &output_tables,
+ (gptr*) &output_tables, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"debug-info", 'T', "Print some debug info at exit.", (gptr*) &info_flag,
+ (gptr*) &info_flag, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"tee", OPT_TEE,
+ "Append everything into outfile. See interactive help (\\h) also. Does not work in batch mode.",
+ 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
#ifndef DONT_ALLOW_USER_CHANGE
- {"user", required_argument, 0, 'u'},
+ {"user", 'u', "User for login if not current user.", (gptr*) &current_user,
+ (gptr*) &current_user, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
#endif
- {"unbuffered", no_argument, 0, 'n'},
- {"verbose", no_argument, 0, 'v'},
- {"version", no_argument, 0, 'V'},
- {"vertical", no_argument, 0, 'E'},
- {"wait", optional_argument, 0, 'w'},
- {0, 0, 0, 0}
-};
-
-
-CHANGEABLE_VAR changeable_vars[] = {
- { "connect_timeout", (long*) &opt_connect_timeout, 0, 0, 3600*12, 0, 1},
- { "max_allowed_packet", (long*) &max_allowed_packet,16*1024L*1024L,4096,
- 24*1024L*1024L, MALLOC_OVERHEAD,1024},
- { "net_buffer_length",(long*) &net_buffer_length,16384,1024,16*1024*1024L,
- MALLOC_OVERHEAD,1024},
- { "select_limit", (long*) &select_limit, 1000L, 1, ~0L, 0, 1},
- { "max_join_size", (long*) &max_join_size, 1000000L, 1, ~0L, 0, 1},
- { 0, 0, 0, 0, 0, 0, 0}
+ {"safe-updates", 'U', "Only allow UPDATE and DELETE that uses keys.",
+ (gptr*) &safe_updates, (gptr*) &safe_updates, 0, GET_BOOL, OPT_ARG, 0, 0,
+ 0, 0, 0, 0},
+ {"i-am-a-dummy", 'U', "Synonym for option --safe-updates, -U.",
+ (gptr*) &safe_updates, (gptr*) &safe_updates, 0, GET_BOOL, OPT_ARG, 0, 0,
+ 0, 0, 0, 0},
+ {"verbose", 'v', "Write more. (-v -v -v gives the table output format)", 0,
+ 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"version", 'V', "Output version information and exit.", 0, 0, 0,
+ GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"wait", 'w', "Wait and retry if connection is down.", 0, 0, 0, GET_NO_ARG,
+ NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"connect_timeout", OPT_CONNECT_TIMEOUT, "", (gptr*) &opt_connect_timeout,
+ (gptr*) &opt_connect_timeout, 0, GET_ULONG, REQUIRED_ARG, 0, 0, 3600*12, 0,
+ 0, 1},
+ {"max_allowed_packet", OPT_MAX_ALLOWED_PACKET, "",
+ (gptr*) &max_allowed_packet, (gptr*) &max_allowed_packet, 0, GET_ULONG,
+ REQUIRED_ARG, 16 *1024L*1024L, 4096, 512*1024L*1024L, MALLOC_OVERHEAD,
+ 1024, 0},
+ {"net_buffer_length", OPT_NET_BUFFER_LENGTH, "",
+ (gptr*) &net_buffer_length, (gptr*) &net_buffer_length, 0, GET_ULONG,
+ REQUIRED_ARG, 16384, 1024, 512*1024*1024L, MALLOC_OVERHEAD, 1024, 0},
+ {"select_limit", OPT_SELECT_LIMIT, "", (gptr*) &select_limit,
+ (gptr*) &select_limit, 0, GET_ULONG, REQUIRED_ARG, 1000L, 1, ~0L, 0, 1, 0},
+ {"max_join_size", OPT_MAX_JOIN_SIZE, "", (gptr*) &max_join_size,
+ (gptr*) &max_join_size, 0, GET_ULONG, REQUIRED_ARG, 1000000L, 1, ~0L, 0, 1,
+ 0},
+ { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
};
@@ -451,298 +594,171 @@ static void usage(int version)
my_progname, VER, MYSQL_SERVER_VERSION, SYSTEM_TYPE, MACHINE_TYPE);
if (version)
return;
- puts("Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB");
- puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software,\nand you are welcome to modify and redistribute it under the GPL license\n");
- printf("Usage: %s [OPTIONS] [database]\n", my_progname);
- printf("\n\
- -?, --help Display this help and exit.\n\
- -A, --no-auto-rehash No automatic rehashing. One has to use 'rehash' to\n\
- get table and field completion. This gives a quicker\n\
- start of mysql and disables rehashing on reconnect.\n\
- -B, --batch Print results with a tab as separator, each row on\n\
- a new line. Doesn't use history file.\n\
- --character-sets-dir=...\n\
- Directory where character sets are located.\n\
- -C, --compress Use compression in server/client protocol.\n");
-#ifndef DBUG_OFF
- printf("\
- -#, --debug[=...] Debug log. Default is '%s'.\n",default_dbug_option);
-#endif
- printf("\
- -D, --database=.. Database to use.\n\
- --default-character-set=...\n\
- Set the default character set.\n\
- -e, --execute=... Execute command and quit. (Output like with --batch)\n\
- -E, --vertical Print the output of a query (rows) vertically.\n\
- -f, --force Continue even if we get an sql error.\n\
- -g, --no-named-commands\n\
- Named commands are disabled. Use \\* form only, or\n\
- use named commands only in the beginning of a line\n\
- ending with a semicolon (;) Since version 10.9 the\n\
- client now starts with this option ENABLED by\n\
- default! Disable with '-G'. Long format commands\n\
- still work from the first line.\n\
- -G, --enable-named-commands\n\
- Named commands are enabled. Opposite to -g.\n\
- -i, --ignore-spaces Ignore spaces after function names.\n\
- -h, --host=... Connect to host.\n\
- -H, --html Produce HTML output.\n\
- --local-infile=[1|0] Enable/disable LOAD DATA LOCAL INFILE\n\
- -L, --skip-line-numbers\n\
- Don't write line number for errors.\n");
-#ifndef __WIN__
- printf("\
- --no-pager Disable pager and print to stdout. See interactive\n\
- help (\\h) also.\n");
-#endif
- printf("\
- --no-tee Disable outfile. See interactive help (\\h) also.\n\
- -n, --unbuffered Flush buffer after each query.\n\
- -N, --skip-column-names\n\
- Don't write column names in results.\n\
- -O, --set-variable var=option\n\
- Give a variable an value. --help lists variables.\n\
- -o, --one-database Only update the default database. This is useful\n\
- for skipping updates to other database in the update\n\
- log.\n");
-#ifndef __WIN__
- printf("\
- --pager[=...] Pager to use to display results. If you don't supply\n\
- an option the default pager is taken from your ENV\n\
- variable PAGER (%s).\n\
- Valid pagers are less, more, cat [> filename], etc.\n\
- See interactive help (\\h) also. This option does\n\
- not work in batch mode.\n", getenv("PAGER") ? getenv("PAGER") : "");
-#endif
- printf("\
- -p[password], --password[=...]\n\
- Password to use when connecting to server\n\
- If password is not given it's asked from the tty.\n");
-#ifdef __WIN__
- puts(" -W, --pipe Use named pipes to connect to server");
-#endif
- printf("\n\
- -P, --port=... Port number to use for connection.\n\
- -q, --quick Don't cache result, print it row by row. This may\n\
- slow down the server if the output is suspended.\n\
- Doesn't use history file.\n\
- -r, --raw Write fields without conversion. Used with --batch\n\
- -s, --silent Be more silent.\n\
- -S --socket=... Socket file to use for connection.\n");
-#include "sslopt-usage.h"
- printf("\
- -t, --table Output in table format.\n\
- -T, --debug-info Print some debug info at exit.\n\
- --tee=... Append everything into outfile. See interactive help\n\
- (\\h) also. Does not work in batch mode.\n");
-#ifndef DONT_ALLOW_USER_CHANGE
- printf("\
- -u, --user=# User for login if not current user.\n");
-#endif
printf("\
- -U, --safe-updates[=#], --i-am-a-dummy[=#]\n\
- Only allow UPDATE and DELETE that uses keys.\n\
- -v, --verbose Write more. (-v -v -v gives the table output format)\n\
- -V, --version Output version information and exit.\n\
- -w, --wait Wait and retry if connection is down.\n");
- print_defaults("my",load_default_groups);
-
- printf("\nPossible variables for option --set-variable (-O) are:\n");
- for (uint i=0 ; changeable_vars[i].name ; i++)
- printf("%-20s current value: %lu\n",
- changeable_vars[i].name,
- (ulong) *changeable_vars[i].varptr);
+Copyright (C) 2002 MySQL AB\n\
+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");
+ printf("Usage: %s [OPTIONS] [database]\n", my_progname);
+ my_print_help(my_long_options);
+ print_defaults("my", load_default_groups);
+ my_print_variables(my_long_options);
}
-
-static int get_options(int argc, char **argv)
+static my_bool
+get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
+ char *argument)
{
- int c,option_index=0;
- bool tty_password=0;
-
- set_all_changeable_vars(changeable_vars);
- while ((c=getopt_long(argc,argv,
- (char*) "?ABCD:LfgGHinNoqrstTU::vVw::WEe:h:O:P:S:u:#::p::",
- long_options, &option_index)) != EOF)
- {
- switch(c) {
- case OPT_DEFAULT_CHARSET:
- default_charset= optarg;
- break;
- case OPT_CHARSETS_DIR:
- charsets_dir= optarg;
- break;
- case OPT_TEE:
- if (!opt_outfile && strlen(optarg))
- {
- strmov(outfile, optarg);
- opt_outfile=1;
- init_tee();
- }
- break;
- case OPT_NOTEE:
+ switch(optid) {
+ case OPT_CHARSETS_DIR:
+ strmov(mysql_charsets_dir, argument);
+ charsets_dir = mysql_charsets_dir;
+ break;
+ case OPT_LOCAL_INFILE:
+ using_opt_local_infile=1;
+ break;
+ case OPT_TEE:
+ if (argument == disabled_my_option)
+ {
if (opt_outfile)
end_tee();
- opt_outfile=0;
- break;
- case OPT_PAGER:
- opt_nopager=0;
- if (optarg)
- strmov(pager, optarg);
+ }
+ else
+ init_tee(argument);
+ break;
+ case OPT_NOTEE:
+ printf("WARNING: option deprecated; use --disable-tee instead.\n");
+ if (opt_outfile)
+ end_tee();
+ break;
+ case OPT_PAGER:
+ if (argument == disabled_my_option)
+ opt_nopager= 1;
+ else
+ {
+ opt_nopager= 0;
+ if (argument)
+ strmov(pager, argument);
else
- {
- char *pagpoint = getenv("PAGER");
- if (!((char*) (pagpoint)))
- {
- strmov(pager, "stdout");
- opt_nopager=1;
- }
- else
- strmov(pager, pagpoint);
- }
+ strmov(pager, default_pager);
strmov(default_pager, pager);
- break;
- case OPT_NOPAGER:
- opt_nopager=1;
- break;
- case 'D':
- my_free(current_db,MYF(MY_ALLOW_ZERO_PTR));
- current_db=my_strdup(optarg,MYF(MY_WME));
- break;
- case 'e':
- status.batch=1;
- status.add_to_history=0;
- batch_readline_end(status.line_buff); // If multiple -e
- if (!(status.line_buff=batch_readline_command(optarg)))
- return 1;
- ignore_errors=0;
- break;
- case 'f':
- ignore_errors=1;
- break;
- case 'h':
- my_free(current_host,MYF(MY_ALLOW_ZERO_PTR));
- current_host=my_strdup(optarg,MYF(MY_WME));
- break;
-#ifndef DONT_ALLOW_USER_CHANGE
- case 'u':
- my_free(current_user,MYF(MY_ALLOW_ZERO_PTR));
- current_user= my_strdup(optarg,MYF(MY_WME));
- break;
-#endif
- case 'U':
- if (!optarg)
- safe_updates=1;
- else
- safe_updates=atoi(optarg) != 0;
- break;
- case 'o':
- one_database=skip_updates=1;
- break;
- case 'O':
- if (set_changeable_var(optarg, changeable_vars))
- {
- usage(0);
- return(1);
- }
- break;
- case 'p':
- if (optarg)
- {
- char *start=optarg;
- my_free(opt_password,MYF(MY_ALLOW_ZERO_PTR));
- opt_password=my_strdup(optarg,MYF(MY_FAE));
- while (*optarg) *optarg++= 'x'; // Destroy argument
- if (*start)
- start[1]=0;
- }
- else
- tty_password=1;
- break;
- case 't':
- output_tables=1;
- break;
- case 'r':
- opt_raw_data=1;
- break;
- case '#':
- DBUG_PUSH(optarg ? optarg : default_dbug_option);
- info_flag=1;
- break;
- case 'q': quick=1; break;
- case 's': opt_silent++; break;
- case 'T': info_flag=1; break;
- case 'n': unbuffered=1; break;
- case 'v': verbose++; break;
- case 'E': vertical=1; break;
- case 'w':
- wait_flag=1;
- if(optarg) wait_time = atoi(optarg) ;
- break;
- case 'A': no_rehash=1; break;
- case 'G': no_named_cmds=0; break;
- case 'g': no_named_cmds=1; break;
- case 'H': opt_html=1; break;
- case 'i': connect_flag|= CLIENT_IGNORE_SPACE; break;
- case 'B':
- if (!status.batch)
- {
- status.batch=1;
- status.add_to_history=0;
- opt_silent++; // more silent
- }
- break;
- case 'C':
- opt_compress=1;
- break;
- case OPT_LOCAL_INFILE:
- using_opt_local_infile=1;
- opt_local_infile= test(!optarg || atoi(optarg)>0);
- break;
- case 'L':
- skip_line_numbers=1;
- break;
- case 'N':
- skip_column_names=1;
- break;
- case 'P':
- opt_mysql_port= (unsigned int) atoi(optarg);
- break;
- case 'S':
- my_free(opt_mysql_unix_port,MYF(MY_ALLOW_ZERO_PTR));
- opt_mysql_unix_port= my_strdup(optarg,MYF(0));
- break;
- case 'W':
+ }
+ break;
+ case OPT_NOPAGER:
+ printf("WARNING: option deprecated; use --disable-pager instead.\n");
+ opt_nopager= 1;
+ break;
+ case 'A':
+ rehash= 0;
+ break;
+ case 'N':
+ column_names= 0;
+ break;
+ case 'e':
+ status.batch= 1;
+ status.add_to_history= 0;
+ batch_readline_end(status.line_buff); // If multiple -e
+ if (!(status.line_buff= batch_readline_command(argument)))
+ return 1;
+ ignore_errors= 0;
+ break;
+ case 'o':
+ if (argument == disabled_my_option)
+ one_database= 0;
+ else
+ one_database= skip_updates= 1;
+ break;
+ case 'p':
+ if (argument == disabled_my_option)
+ argument= (char*) ""; // Don't require password
+ if (argument)
+ {
+ char *start= argument;
+ my_free(opt_password, MYF(MY_ALLOW_ZERO_PTR));
+ opt_password= my_strdup(argument, MYF(MY_FAE));
+ while (*argument) *argument++= 'x'; // Destroy argument
+ if (*start)
+ start[1]=0 ;
+ }
+ else
+ tty_password= 1;
+ break;
+ case '#':
+ DBUG_PUSH(argument ? argument : default_dbug_option);
+ info_flag= 1;
+ break;
+ case 's':
+ if (argument == disabled_my_option)
+ opt_silent= 0;
+ else
+ opt_silent++;
+ break;
+ case 'v':
+ if (argument == disabled_my_option)
+ verbose= 0;
+ else
+ verbose++;
+ break;
+ case 'B':
+ if (!status.batch)
+ {
+ status.batch= 1;
+ status.add_to_history= 0;
+ opt_silent++; // more silent
+ }
+ break;
+ case 'W':
#ifdef __WIN__
- opt_mysql_unix_port=my_strdup(MYSQL_NAMEDPIPE,MYF(0));
+ opt_mysql_unix_port= my_strdup(MYSQL_NAMEDPIPE, MYF(0));
#endif
- break;
- case 'V': usage(1); exit(0);
- case 'I':
- case '?':
- usage(0);
- exit(0);
-#include "sslopt-case.h"
- default:
- tee_fprintf(stderr,"illegal option: -%c\n",opterr);
- usage(0);
- exit(1);
- }
+ break;
+#include <sslopt-case.h>
+ case 'V':
+ usage(1);
+ exit(0);
+ case 'I':
+ case '?':
+ usage(0);
+ exit(0);
+ }
+ return 0;
+}
+
+
+static int get_options(int argc, char **argv)
+{
+ char *tmp, *pagpoint;
+ int ho_error;
+
+ tmp= (char *) getenv("MYSQL_HOST");
+ if (tmp)
+ current_host= my_strdup(tmp, MYF(MY_WME));
+
+ pagpoint= getenv("PAGER");
+ if (!((char*) (pagpoint)))
+ {
+ strmov(pager, "stdout");
+ opt_nopager= 1;
}
+ else
+ strmov(pager, pagpoint);
+ strmov(default_pager, pager);
+
+ if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option)))
+ exit(ho_error);
+
if (status.batch) /* disable pager and outfile in this case */
{
strmov(default_pager, "stdout");
strmov(pager, "stdout");
- opt_nopager=1;
- opt_outfile=0;
+ opt_nopager= 1;
+ opt_outfile= 0;
+ connect_flag= 0; /* Not in interactive mode */
}
if (default_charset)
{
if (set_default_charset_by_name(default_charset, MYF(MY_WME)))
exit(1);
}
- argc-=optind;
- argv+=optind;
if (argc > 1)
{
usage(0);
@@ -750,23 +766,17 @@ static int get_options(int argc, char **argv)
}
if (argc == 1)
{
- my_free(current_db,MYF(MY_ALLOW_ZERO_PTR));
- current_db= my_strdup(*argv,MYF(MY_WME));
- }
- if (!current_host)
- { /* If we don't have a hostname have a look at MYSQL_HOST */
- char *tmp=(char *) getenv("MYSQL_HOST");
- if (tmp)
- current_host = my_strdup(tmp,MYF(MY_WME));
+ my_free(current_db, MYF(MY_ALLOW_ZERO_PTR));
+ current_db= my_strdup(*argv, MYF(MY_WME));
}
if (tty_password)
- opt_password=get_tty_password(NullS);
+ opt_password= get_tty_password(NullS);
return(0);
}
static int read_lines(bool execute_commands)
{
-#if defined( __WIN__) || defined(OS2)
+#if defined( __WIN__) || defined(OS2) || defined(__NETWARE__)
char linebuffer[254];
#endif
char *line;
@@ -786,30 +796,33 @@ static int read_lines(bool execute_commands)
}
else
{
-#if defined( __WIN__) || defined(OS2)
+ char *prompt= (char*) (glob_buffer.is_empty() ? construct_prompt() :
+ !in_string ? " -> " :
+ in_string == '\'' ?
+ " '> " : " \"> ");
if (opt_outfile && glob_buffer.is_empty())
fflush(OUTFILE);
- tee_fputs(glob_buffer.is_empty() ? "mysql> " :
- !in_string ? " -> " :
- in_string == '\'' ?
- " '> " : " \"> ",stdout);
- linebuffer[0]=(char) sizeof(linebuffer);
- line=_cgets(linebuffer);
-#else
- if (opt_outfile)
+
+#if defined( __WIN__) || defined(OS2) || defined(__NETWARE__)
+ tee_fputs(prompt, stdout);
+#ifdef __NETWARE__
+ line=fgets(linebuffer, sizeof(linebuffer)-1, stdin);
+ /* Remove the '\n' */
{
- if (glob_buffer.is_empty())
- fflush(OUTFILE);
- fputs(glob_buffer.is_empty() ? "mysql> " :
- !in_string ? " -> " :
- in_string == '\'' ?
- " '> " : " \"> ", OUTFILE);
+ char *p = strrchr(line, '\n');
+ if (p != NULL)
+ *p = '\0';
}
- line=readline((char*) (glob_buffer.is_empty() ? "mysql> " :
- !in_string ? " -> " :
- in_string == '\'' ?
- " '> " : " \"> "));
-#endif
+#else
+ linebuffer[0]= (char) sizeof(linebuffer);
+ line= _cgets(linebuffer);
+#endif /* __NETWARE__ */
+#else
+ if (opt_outfile)
+ fputs(prompt, OUTFILE);
+ line= readline(prompt);
+#endif /* defined( __WIN__) || defined(OS2) || defined(__NETWARE__) */
+
if (opt_outfile)
fprintf(OUTFILE, "%s\n", line);
}
@@ -823,9 +836,11 @@ static int read_lines(bool execute_commands)
line[0] == 0))
continue; // Skip comment lines
- /* Check if line is a mysql command line */
- /* (We want to allow help, print and clear anywhere at line start */
- if (execute_commands && (!no_named_cmds || glob_buffer.is_empty())
+ /*
+ Check if line is a mysql command line
+ (We want to allow help, print and clear anywhere at line start
+ */
+ if (execute_commands && (named_cmds || glob_buffer.is_empty())
&& !in_string && (com=find_command(line,0)))
{
if ((*com->func)(&glob_buffer,line) > 0)
@@ -1007,20 +1022,20 @@ static bool add_line(String &buffer,char *line,char *in_string)
return 0;
}
-/* **************************************************************** */
-/* */
-/* Interface to Readline Completion */
-/* */
-/* **************************************************************** */
+/*****************************************************************
+ Interface to Readline Completion
+******************************************************************/
#ifdef HAVE_READLINE
static char *new_command_generator(char *text, int);
static char **new_mysql_completion (char *text, int start, int end);
-/* 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. */
+/*
+ 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.
+*/
char **no_completion (char *text __attribute__ ((unused)),
char *word __attribute__ ((unused)))
@@ -1039,11 +1054,12 @@ static void initialize_readline (char *name)
rl_completion_entry_function=(Function *) no_completion;
}
-/* 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. */
-
+/*
+ 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.
+*/
static char **new_mysql_completion (char *text,
int start __attribute__((unused)),
@@ -1063,67 +1079,72 @@ static char *new_command_generator(char *text,int state)
static entry *e;
static uint i;
- if (!state) {
+ if (!state)
textlen=(uint) strlen(text);
- }
- if (textlen>0) { /* lookup in the hash */
- if (!state) {
+ if (textlen>0)
+ { /* lookup in the hash */
+ if (!state)
+ {
uint len;
b = find_all_matches(&ht,text,(uint) strlen(text),&len);
- if (!b) {
+ if (!b)
return NullS;
- }
e = b->pData;
}
- while (e) {
+ if (e)
+ {
ptr= strdup(e->str);
e = e->pNext;
return ptr;
}
- } else { /* traverse the entire hash, ugly but works */
+ }
+ else
+ { /* traverse the entire hash, ugly but works */
- if (!state) {
- i=0;
+ if (!state)
+ {
/* find the first used bucket */
- while (i<ht.nTableSize) {
- if (ht.arBuckets[i]) {
+ for (i=0 ; i < ht.nTableSize ; i++)
+ {
+ if (ht.arBuckets[i])
+ {
b = ht.arBuckets[i];
e = b->pData;
break;
}
- i++;
}
}
ptr= NullS;
- while (e && !ptr) { /* find valid entry in bucket */
- if ((uint) strlen(e->str)==b->nKeyLength) {
+ while (e && !ptr)
+ { /* find valid entry in bucket */
+ if ((uint) strlen(e->str) == b->nKeyLength)
ptr = strdup(e->str);
- }
/* find the next used entry */
e = e->pNext;
- if (!e) { /* find the next used bucket */
+ if (!e)
+ { /* find the next used bucket */
b = b->pNext;
- if (!b) {
- i++;
- while (i<ht.nTableSize) {
- if (ht.arBuckets[i]) {
+ if (!b)
+ {
+ for (i++ ; i<ht.nTableSize; i++)
+ {
+ if (ht.arBuckets[i])
+ {
b = ht.arBuckets[i];
e = b->pData;
break;
}
- i++;
}
- } else {
- e = b->pData;
}
+ else
+ e = b->pData;
}
}
- if (ptr) {
+ if (ptr)
return ptr;
- }
}
return NullS;
}
@@ -1131,10 +1152,11 @@ static char *new_command_generator(char *text,int state)
/* Build up the completion hash */
-static void build_completion_hash(bool skip_rehash,bool write_info)
+static void build_completion_hash(bool rehash, bool write_info)
{
COMMANDS *cmd=commands;
- static MYSQL_RES *databases=0,*tables=0,*fields;
+ MYSQL_RES *databases=0,*tables=0;
+ MYSQL_RES *fields;
static char ***field_names= 0;
MYSQL_ROW database_row,table_row;
MYSQL_FIELD *sql_field;
@@ -1145,35 +1167,42 @@ static void build_completion_hash(bool skip_rehash,bool write_info)
if (status.batch || quick || !current_db)
DBUG_VOID_RETURN; // We don't need completion in batches
- completion_hash_clean(&ht);
if (tables)
{
mysql_free_result(tables);
tables=0;
}
- if (databases) {
- mysql_free_result(databases);
- databases=0;
- }
/* hash SQL commands */
while (cmd->name) {
add_word(&ht,(char*) cmd->name);
cmd++;
}
- if (skip_rehash)
+ if (!rehash)
DBUG_VOID_RETURN;
+ /* Free old used memory */
+ if (field_names)
+ field_names=0;
+ completion_hash_clean(&ht);
+ free_root(&hash_mem_root,MYF(0));
+
/* hash MySQL functions (to be implemented) */
/* hash all database names */
- if (mysql_query(&mysql,"show databases")==0) {
+ if (mysql_query(&mysql,"show databases") == 0)
+ {
if (!(databases = mysql_store_result(&mysql)))
put_info(mysql_error(&mysql),INFO_INFO);
else
{
while ((database_row=mysql_fetch_row(databases)))
- add_word(&ht,(char*) database_row[0]);
+ {
+ char *str=strdup_root(&hash_mem_root, (char*) database_row[0]);
+ if (str)
+ add_word(&ht,(char*) str);
+ }
+ mysql_free_result(databases);
}
}
/* hash all table names */
@@ -1191,22 +1220,13 @@ You can turn off this feature to get a quicker startup with -A\n\n");
}
while ((table_row=mysql_fetch_row(tables)))
{
- if (!completion_hash_exists(&ht,(char*) table_row[0],
- (uint) strlen((const char*) table_row[0])))
- add_word(&ht,table_row[0]);
+ 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);
}
}
}
- if (field_names) {
- for (i=0; field_names[i]; i++) {
- for (j=0; field_names[i][j]; j++) {
- my_free(field_names[i][j],MYF(0));
- }
- my_free((gptr) field_names[i],MYF(0));
- }
- my_free((gptr) field_names,MYF(0));
- }
- field_names=0;
/* hash all field names, both with the table prefix and without it */
if (!tables) /* no tables */
@@ -1214,36 +1234,37 @@ You can turn off this feature to get a quicker startup with -A\n\n");
DBUG_VOID_RETURN;
}
mysql_data_seek(tables,0);
- field_names = (char ***) my_malloc(sizeof(char **) *
- (uint) (mysql_num_rows(tables)+1),
- MYF(MY_WME));
- if (!field_names)
+ if (!(field_names= (char ***) alloc_root(&hash_mem_root,sizeof(char **) *
+ (uint) (mysql_num_rows(tables)+1))))
+ {
+ mysql_free_result(tables);
DBUG_VOID_RETURN;
+ }
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);
- field_names[i] = (char **) my_malloc(sizeof(char *)*(num_fields*2+1),
- MYF(0));
- if (!field_names[i])
- {
- continue;
- }
+ if (!(field_names[i] = (char **) alloc_root(&hash_mem_root,
+ sizeof(char *) *
+ (num_fields*2+1))))
+ break;
field_names[i][num_fields*2]='\0';
j=0;
while ((sql_field=mysql_fetch_field(fields)))
{
sprintf(buf,"%s.%s",table_row[0],sql_field->name);
- field_names[i][j] = my_strdup(buf,MYF(0));
+ field_names[i][j] = strdup_root(&hash_mem_root,buf);
add_word(&ht,field_names[i][j]);
- field_names[i][num_fields+j] = my_strdup(sql_field->name,MYF(0));
+ field_names[i][num_fields+j] = strdup_root(&hash_mem_root,
+ sql_field->name);
if (!completion_hash_exists(&ht,field_names[i][num_fields+j],
(uint) strlen(field_names[i][num_fields+j])))
add_word(&ht,field_names[i][num_fields+j]);
j++;
}
+ mysql_free_result(fields);
}
else
{
@@ -1253,20 +1274,18 @@ You can turn off this feature to get a quicker startup with -A\n\n");
}
i++;
}
+ mysql_free_result(tables);
field_names[i]=0; // End pointer
DBUG_VOID_RETURN;
}
-
/* for gnu readline */
#ifndef HAVE_INDEX
-#ifdef __cplusplus
extern "C" {
-#endif
-extern char *index(const char *,pchar c),*rindex(const char *,pchar);
+extern char *index(const char *,int c),*rindex(const char *,int);
-char *index(const char *s,pchar c)
+char *index(const char *s,int c)
{
for (;;)
{
@@ -1275,7 +1294,7 @@ char *index(const char *s,pchar c)
}
}
-char *rindex(const char *s,pchar c)
+char *rindex(const char *s,int c)
{
reg3 char *t;
@@ -1283,19 +1302,19 @@ char *rindex(const char *s,pchar c)
do if (*s == (char) c) t = (char*) s; while (*s++);
return (char*) t;
}
-#ifdef __cplusplus
}
#endif
-#endif
#endif /* HAVE_READLINE */
+
static int reconnect(void)
{
if (!status.batch)
{
put_info("No connection. Trying to reconnect...",INFO_INFO);
(void) com_connect((String *) 0, 0);
- if(!no_rehash) com_rehash(NULL, NULL);
+ if (rehash)
+ com_rehash(NULL, NULL);
}
if (!connected)
return put_info("Can't connect to the server\n",INFO_ERROR);
@@ -1313,9 +1332,13 @@ com_help (String *buffer __attribute__((unused)),
{
reg1 int i;
- put_info("\nMySQL commands:",INFO_INFO);
- if (no_named_cmds)
- put_info("Note that all text commands must be first on line and end with ';'",INFO_INFO);
+ put_info("\nFor the complete MySQL Manual online visit:\n http://www.mysql.com/documentation\n", INFO_INFO);
+ put_info("For info on technical support from MySQL developers visit:\n http://www.mysql.com/support\n", INFO_INFO);
+ put_info("For info on MySQL books, utilities, consultants, etc. visit:\n http://www.mysql.com/portal\n", INFO_INFO);
+ put_info("List of all MySQL commands:", INFO_INFO);
+ if (!named_cmds)
+ put_info(" (Commands must appear first on line and end with ';')\n",
+ INFO_INFO);
for (i = 0; commands[i].name; i++)
{
if (commands[i].func)
@@ -1342,10 +1365,10 @@ com_clear(String *buffer,char *line __attribute__((unused)))
/*
-** Execute command
-** Returns: 0 if ok
-** -1 if not fatal error
-** 1 if fatal error
+ Execute command
+ Returns: 0 if ok
+ -1 if not fatal error
+ 1 if fatal error
*/
@@ -1363,7 +1386,7 @@ com_go(String *buffer,char *line __attribute__((unused)))
old_buffer.copy();
}
- /* Remove garbage for nicer messages */
+ /* Remove garbage for nicer messages */
LINT_INIT(buff[0]);
remove_cntrl(*buffer);
@@ -1443,6 +1466,8 @@ com_go(String *buffer,char *line __attribute__((unused)))
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)
@@ -1479,7 +1504,7 @@ com_go(String *buffer,char *line __attribute__((unused)))
static void init_pager()
{
-#if !defined( __WIN__) && !defined( OS2)
+#ifdef USE_POPEN
if (!opt_nopager)
{
if (!(PAGER= popen(pager, "w")))
@@ -1495,25 +1520,36 @@ static void init_pager()
static void end_pager()
{
-#if !defined( __WIN__) && !defined( OS2)
+#ifdef USE_POPEN
if (!opt_nopager)
pclose(PAGER);
#endif
}
-static void init_tee()
+
+static void init_tee(const char *file_name)
{
- if (!(OUTFILE= my_fopen(outfile, O_APPEND | O_WRONLY, MYF(MY_WME))))
+ FILE* new_outfile;
+ if (opt_outfile)
+ end_tee();
+ if (!(new_outfile= my_fopen(file_name, O_APPEND | O_WRONLY, MYF(MY_WME))))
{
- opt_outfile=0;
- init_pager();
+ tee_fprintf(stdout, "Error logging to file '%s'\n", file_name);
return;
}
+ OUTFILE = new_outfile;
+ strmake(outfile, file_name, FN_REFLEN-1);
+ tee_fprintf(stdout, "Logging to file '%s'\n", file_name);
+ opt_outfile= 1;
+ return;
}
+
static void end_tee()
{
my_fclose(OUTFILE, MYF(0));
+ OUTFILE= 0;
+ opt_outfile= 0;
return;
}
@@ -1552,6 +1588,9 @@ print_table_data(MYSQL_RES *result)
MYSQL_ROW cur;
MYSQL_FIELD *field;
bool *num_flag;
+#ifdef __NETWARE__
+ uint lines= 0;
+#endif
num_flag=(bool*) my_alloca(sizeof(bool)*mysql_num_fields(result));
if (info_flag)
@@ -1562,7 +1601,7 @@ print_table_data(MYSQL_RES *result)
separator.copy("+",1);
while ((field = mysql_fetch_field(result)))
{
- uint length=skip_column_names ? 0 : (uint) strlen(field->name);
+ uint length= column_names ? (uint) strlen(field->name) : 0;
if (quick)
length=max(length,field->length);
else
@@ -1574,7 +1613,7 @@ print_table_data(MYSQL_RES *result)
separator.append('+');
}
tee_puts(separator.c_ptr(), PAGER);
- if (!skip_column_names)
+ if (column_names)
{
mysql_field_seek(result,0);
(void) tee_fputs("|", PAGER);
@@ -1588,38 +1627,47 @@ print_table_data(MYSQL_RES *result)
tee_puts(separator.c_ptr(), PAGER);
}
- while ((cur = mysql_fetch_row(result)))
+ while ((cur= mysql_fetch_row(result)))
{
(void) tee_fputs("|", PAGER);
- mysql_field_seek(result,0);
- for (uint off=0 ; off < mysql_num_fields(result); off++)
+ mysql_field_seek(result, 0);
+ for (uint off= 0; off < mysql_num_fields(result); off++)
{
- const char *str=cur[off] ? cur[off] : "NULL";
- field = mysql_fetch_field(result);
- uint length=field->max_length;
+ const char *str= cur[off] ? cur[off] : "NULL";
+ field= mysql_fetch_field(result);
+ uint length= field->max_length;
if (length > MAX_COLUMN_LENGTH)
{
- tee_fputs(str,PAGER); tee_fputs(" |",PAGER);
+ tee_fputs(str, PAGER);
+ tee_fputs(" |", PAGER);
}
else
tee_fprintf(PAGER, num_flag[off] ? "%*s |" : " %-*s|",
length, str);
}
(void) tee_fputs("\n", PAGER);
+#ifdef __NETWARE__
+ // on a long result the screen could hog the cpu
+ if ((lines++ & 1023) == 0) pthread_yield();
+#endif
}
tee_puts(separator.c_ptr(), PAGER);
my_afree((gptr) num_flag);
}
+
static void
print_table_data_html(MYSQL_RES *result)
{
- MYSQL_ROW cur;
- MYSQL_FIELD *field;
+ MYSQL_ROW cur;
+ MYSQL_FIELD *field;
+#ifdef __NETWARE__
+ uint lines= 0;
+#endif
mysql_field_seek(result,0);
(void) tee_fputs("<TABLE BORDER=1><TR>", PAGER);
- if (!skip_column_names)
+ if (column_names)
{
while((field = mysql_fetch_field(result)))
{
@@ -1640,11 +1688,54 @@ print_table_data_html(MYSQL_RES *result)
(void) tee_fputs("</TD>", PAGER);
}
(void) tee_fputs("</TR>", PAGER);
+#ifdef __NETWARE__
+ // on a long result the screen could hog the cpu
+ if ((lines++ & 1023) == 0) pthread_yield();
+#endif
}
(void) tee_fputs("</TABLE>", PAGER);
}
+static void
+print_table_data_xml(MYSQL_RES *result)
+{
+ MYSQL_ROW cur;
+ MYSQL_FIELD *fields;
+#ifdef __NETWARE__
+ uint lines= 0;
+#endif
+
+ mysql_field_seek(result,0);
+
+ tee_fputs("<?xml version=\"1.0\"?>\n\n<resultset statement=\"", PAGER);
+ xmlencode_print(glob_buffer.ptr(), strlen(glob_buffer.ptr()));
+ tee_fputs("\">", PAGER);
+
+ fields = mysql_fetch_fields(result);
+ while ((cur = mysql_fetch_row(result)))
+ {
+ (void) tee_fputs("\n <row>\n", PAGER);
+ for (uint i=0; i < mysql_num_fields(result); i++)
+ {
+ ulong *lengths=mysql_fetch_lengths(result);
+ tee_fprintf(PAGER, "\t<%s>", (fields[i].name ?
+ (fields[i].name[0] ? fields[i].name :
+ " &nbsp; ") : "NULL"));
+ xmlencode_print(cur[i], lengths[i]);
+ tee_fprintf(PAGER, "</%s>\n", (fields[i].name ?
+ (fields[i].name[0] ? fields[i].name :
+ " &nbsp; ") : "NULL"));
+ }
+ (void) tee_fputs(" </row>\n", PAGER);
+#ifdef __NETWARE__
+ // on a long result the screen could hog the cpu
+ if ((lines++ & 1023) == 0) pthread_yield();
+#endif
+ }
+ (void) tee_fputs("</resultset>\n", PAGER);
+}
+
static void
print_table_data_vertically(MYSQL_RES *result)
@@ -1673,6 +1764,40 @@ print_table_data_vertically(MYSQL_RES *result)
tee_fprintf(PAGER, "%*s: ",(int) max_length,field->name);
tee_fprintf(PAGER, "%s\n",cur[off] ? (char*) cur[off] : "NULL");
}
+#ifdef __NETWARE__
+ // on a long result the screen could hog the cpu
+ if ((row_count & 1023) == 0) pthread_yield();
+#endif
+ }
+}
+
+
+static const char
+*array_value(const char **array, char key)
+{
+ int x;
+ for (x= 0; array[x]; x+= 2)
+ if (*array[x] == key)
+ return array[x + 1];
+ return 0;
+}
+
+
+static void
+xmlencode_print(const char *src, uint length)
+{
+ if (!src)
+ tee_fputs("NULL", PAGER);
+ else
+ {
+ 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);
+ }
}
}
@@ -1706,7 +1831,7 @@ safe_put_field(const char *pos,ulong length)
tee_fputs("\\n", PAGER); // This too
else if (*pos == '\\')
tee_fputs("\\\\", PAGER);
- else
+ else
tee_putc(*pos, PAGER);
}
}
@@ -1720,7 +1845,7 @@ print_tab_data(MYSQL_RES *result)
MYSQL_FIELD *field;
ulong *lengths;
- if (opt_silent < 2 && !skip_column_names)
+ if (opt_silent < 2 && column_names)
{
int first=0;
while ((field = mysql_fetch_field(result)))
@@ -1738,7 +1863,7 @@ print_tab_data(MYSQL_RES *result)
for (uint off=1 ; off < mysql_num_fields(result); off++)
{
(void) tee_fputs("\t", PAGER);
- safe_put_field(cur[off],lengths[off]);
+ safe_put_field(cur[off], lengths[off]);
}
(void) tee_fputs("\n", PAGER);
}
@@ -1757,57 +1882,51 @@ com_tee(String *buffer, char *line __attribute__((unused)))
{
if (!strlen(outfile))
{
- printf("No previous outfile available, you must give the filename!\n");
- opt_outfile=0;
+ printf("No previous outfile available, you must give a filename!\n");
return 0;
}
- }
- else
- {
- while (isspace(*param))
- param++;
- end= strend(param);
- while (end > file_name && (isspace(end[-1]) || iscntrl(end[-1])))
- end--;
- end[0]= 0;
- if ((*(end - 1) == '"' && *param == '"') ||
- (*(end - 1) == '\'' && *param == '\''))
+ else if (opt_outfile)
{
- *--end= 0;
- param++;
+ tee_fprintf(stdout, "Currently logging to file '%s'\n", outfile);
+ return 0;
}
- strmake(file_name, param, sizeof(file_name) - 1);
- strmov(outfile, file_name);
+ else
+ param = outfile; //resume using the old outfile
}
- if (!strlen(outfile))
+
+ /* eliminate the spaces before the parameters */
+ while (isspace(*param))
+ param++;
+ end= strmake(file_name, param, sizeof(file_name) - 1);
+ /* remove end space from command line */
+ while (end > file_name && (isspace(end[-1]) || iscntrl(end[-1])))
+ end--;
+ end[0]= 0;
+ if (end == file_name)
{
printf("No outfile specified!\n");
return 0;
}
- if (opt_outfile)
- end_tee();
- init_tee();
- opt_outfile= 1;
- tee_fprintf(stdout, "Logging to file '%s'\n", outfile);
+ init_tee(file_name);
return 0;
}
+
static int
com_notee(String *buffer __attribute__((unused)),
char *line __attribute__((unused)))
{
if (opt_outfile)
end_tee();
- opt_outfile=0;
tee_fprintf(stdout, "Outfile disabled.\n");
return 0;
}
/*
-** Sorry, this command is not available in Windows.
+ Sorry, this command is not available in Windows.
*/
-#ifndef __WIN__
+#ifdef USE_POPEN
static int
com_pager(String *buffer, char *line __attribute__((unused)))
{
@@ -1818,9 +1937,9 @@ com_pager(String *buffer, char *line __attribute__((unused)))
/* Skip space from file name */
while (isspace(*line))
line++;
- if (!(param = strchr(line, ' '))) // if pager was not given, use the default
+ if (!(param= strchr(line, ' '))) // if pager was not given, use the default
{
- if (!strlen(default_pager))
+ if (!default_pager[0])
{
tee_fprintf(stdout, "Default pager wasn't set, using stdout.\n");
opt_nopager=1;
@@ -1860,10 +1979,10 @@ com_nopager(String *buffer __attribute__((unused)),
/*
-** Sorry, you can't send the result to an editor in Win32
+ Sorry, you can't send the result to an editor in Win32
*/
-#ifndef __WIN__
+#ifdef USE_POPEN
static int
com_edit(String *buffer,char *line __attribute__((unused)))
{
@@ -1911,6 +2030,10 @@ static int
com_quit(String *buffer __attribute__((unused)),
char *line __attribute__((unused)))
{
+#ifdef __NETWARE__
+ // let the screen auto close on a normal shutdown
+ setscreenmode(SCR_AUTOCLOSE_ON_EXIT);
+#endif
status.exit_status=0;
return 1;
}
@@ -1920,11 +2043,36 @@ com_rehash(String *buffer __attribute__((unused)),
char *line __attribute__((unused)))
{
#ifdef HAVE_READLINE
- build_completion_hash(0,0);
+ build_completion_hash(1, 0);
#endif
return 0;
}
+
+#ifdef USE_POPEN
+static int
+com_shell(String *buffer, char *line __attribute__((unused)))
+{
+ char *shell_cmd;
+ if (!(shell_cmd = strchr(line, ' ')))
+ {
+ put_info("Usage: \\! shell-command", INFO_ERROR);
+ return -1;
+ }
+ /*
+ The output of the shell command does not
+ get directed to the pager or the outfile
+ */
+ if (system(shell_cmd) == -1)
+ {
+ put_info(strerror(errno), INFO_ERROR, errno);
+ return -1;
+ }
+ return 0;
+}
+#endif
+
+
static int
com_print(String *buffer,char *line __attribute__((unused)))
{
@@ -1941,7 +2089,7 @@ static int
com_connect(String *buffer, char *line)
{
char *tmp,buff[256];
- bool save_rehash=no_rehash;
+ bool save_rehash= rehash;
int error;
if (buffer)
@@ -1963,13 +2111,13 @@ com_connect(String *buffer, char *line)
}
}
else
- no_rehash=1; // Quick re-connect
+ rehash= 0; // Quick re-connect
buffer->length(0); // command used
}
else
- no_rehash=1;
+ rehash= 0;
error=sql_connect(current_host,current_db,current_user,opt_password,0);
- no_rehash=save_rehash;
+ rehash= save_rehash;
if (connected)
{
@@ -2055,7 +2203,7 @@ com_use(String *buffer __attribute__((unused)), char *line)
if (!current_db || cmp_database(current_db,tmp))
{
if (one_database)
- skip_updates=1;
+ skip_updates= 1;
else
{
/*
@@ -2077,12 +2225,12 @@ com_use(String *buffer __attribute__((unused)), char *line)
my_free(current_db,MYF(MY_ALLOW_ZERO_PTR));
current_db=my_strdup(tmp,MYF(MY_WME));
#ifdef HAVE_READLINE
- build_completion_hash(no_rehash,1);
+ build_completion_hash(rehash, 1);
#endif
}
}
else
- skip_updates=0;
+ skip_updates= 0;
put_info("Database changed",INFO_INFO);
return 0;
}
@@ -2092,11 +2240,8 @@ static int
sql_real_connect(char *host,char *database,char *user,char *password,
uint silent)
{
- if (connected)
- { /* if old is open, close it first */
- mysql_close(&mysql);
- connected= 0;
- }
+ mysql_close(&mysql);
+ connected= 0;
mysql_init(&mysql);
if (opt_connect_timeout)
{
@@ -2111,7 +2256,7 @@ sql_real_connect(char *host,char *database,char *user,char *password,
#ifdef HAVE_OPENSSL
if (opt_use_ssl)
mysql_ssl_set(&mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
- opt_ssl_capath);
+ opt_ssl_capath, opt_ssl_cipher);
#endif
if (safe_updates)
{
@@ -2121,8 +2266,8 @@ sql_real_connect(char *host,char *database,char *user,char *password,
select_limit,max_join_size);
mysql_options(&mysql, MYSQL_INIT_COMMAND, init_command);
}
- if (!mysql_real_connect(&mysql,host,user,password,
- database,opt_mysql_port,opt_mysql_unix_port,
+ if (!mysql_real_connect(&mysql, host, user, password,
+ database, opt_mysql_port, opt_mysql_unix_port,
connect_flag))
{
if (!silent ||
@@ -2138,7 +2283,7 @@ sql_real_connect(char *host,char *database,char *user,char *password,
connected=1;
mysql.reconnect=info_flag ? 1 : 0; // We want to know if this happens
#ifdef HAVE_READLINE
- build_completion_hash(no_rehash,1);
+ build_completion_hash(rehash, 1);
#endif
return 0;
}
@@ -2183,7 +2328,7 @@ static int
com_status(String *buffer __attribute__((unused)),
char *line __attribute__((unused)))
{
- char *status;
+ const char *status;
tee_puts("--------------", stdout);
usage(1); /* Print version */
if (connected)
@@ -2199,6 +2344,13 @@ com_status(String *buffer __attribute__((unused)),
tee_fprintf(stdout, "Current user:\t\t%s\n",cur[1]);
(void) mysql_fetch_row(result); // Read eof
}
+#ifdef HAVE_OPENSSL
+ if (mysql.net.vio->ssl_ && SSL_get_cipher(mysql.net.vio->ssl_))
+ tee_fprintf(stdout, "SSL:\t\t\tCipher in use is %s\n",
+ SSL_get_cipher(mysql.net.vio->ssl_));
+ else
+#endif /* HAVE_OPENSSL */
+ tee_puts("SSL:\t\t\tNot in use", stdout);
}
else
{
@@ -2213,7 +2365,7 @@ com_status(String *buffer __attribute__((unused)),
tee_fprintf(stdout, "\nAll updates ignored to this database\n");
vidattr(A_NORMAL);
}
-#ifndef __WIN__
+#ifdef USE_POPEN
tee_fprintf(stdout, "Current pager:\t\t%s\n", pager);
tee_fprintf(stdout, "Using outfile:\t\t'%s'\n", opt_outfile ? outfile : "");
#endif
@@ -2232,11 +2384,11 @@ com_status(String *buffer __attribute__((unused)),
if ((status=mysql_stat(&mysql)) && !mysql_error(&mysql)[0])
{
- char *pos,buff[40];
ulong sec;
- pos=strchr(status,' ');
- *pos++=0;
- tee_fprintf(stdout, "%s\t\t\t", status); /* print label */
+ char buff[40];
+ const char *pos= strchr(status,' ');
+ /* print label */
+ tee_fprintf(stdout, "%.*s\t\t\t", (int) (pos-status), status);
if ((status=str2int(pos,10,0,LONG_MAX,(long*) &sec)))
{
nice_time((double) sec,buff,0);
@@ -2270,7 +2422,7 @@ static int
put_info(const char *str,INFO_TYPE info_type,uint error)
{
static int inited=0;
-
+
if (status.batch)
{
if (info_type == INFO_ERROR)
@@ -2279,7 +2431,7 @@ put_info(const char *str,INFO_TYPE info_type,uint error)
fprintf(stderr,"ERROR");
if (error)
(void) fprintf(stderr," %d",error);
- if (status.query_start_line && ! skip_line_numbers)
+ if (status.query_start_line && line_numbers)
{
(void) fprintf(stderr," at line %lu",status.query_start_line);
if (status.file_name)
@@ -2307,7 +2459,8 @@ put_info(const char *str,INFO_TYPE info_type,uint error)
}
if (info_type == INFO_ERROR)
{
- putchar('\007'); /* This should make a bell */
+ if (!opt_nobeep)
+ putchar('\007'); /* This should make a bell */
vidattr(A_STANDOUT);
if (error)
(void) tee_fprintf(stderr, "ERROR %d: ", error);
@@ -2385,17 +2538,19 @@ void tee_putc(int c, FILE *file)
putc(c, OUTFILE);
}
-#if defined( __WIN__) || defined( OS2)
+#if defined( __WIN__) || defined( OS2) || defined(__NETWARE__)
#include <time.h>
#else
#include <sys/times.h>
+#ifdef _SC_CLK_TCK // For mit-pthreads
#undef CLOCKS_PER_SEC
#define CLOCKS_PER_SEC (sysconf(_SC_CLK_TCK))
#endif
+#endif
static ulong start_timer(void)
{
-#if defined( __WIN__) || defined( OS2)
+#if defined( __WIN__) || defined( OS2) || defined(__NETWARE__)
return clock();
#else
struct tms tms_tmp;
@@ -2450,6 +2605,183 @@ static void mysql_end_timer(ulong start_time,char *buff)
strmov(strend(buff),")");
}
+static const char* construct_prompt()
+{
+ //erase the old prompt
+ processed_prompt.free();
+ //get the date struct
+ time_t lclock = time(NULL);
+ struct tm *t = localtime(&lclock);
+ //parse thru the settings for the prompt
+ for (char *c = current_prompt; *c ; *c++)
+ {
+ if (*c != PROMPT_CHAR)
+ processed_prompt.append(*c);
+ else
+ {
+ switch (*++c) {
+ case '\0':
+ //stop it from going beyond if ends with %
+ c--;
+ break;
+ case 'c':
+ add_int_to_prompt(++prompt_counter);
+ break;
+ case 'v':
+ processed_prompt.append(mysql_get_server_info(&mysql));
+ break;
+ case 'd':
+ processed_prompt.append(current_db ? current_db : "(none)");
+ break;
+ case 'h':
+ {
+ const char *prompt=mysql_get_host_info(&mysql);
+ if (strstr(prompt, "Localhost"))
+ processed_prompt.append("localhost");
+ else
+ {
+ const char *end=strcend(prompt,' ');
+ processed_prompt.append(prompt, (uint) (end-prompt));
+ }
+ break;
+ }
+ case 'p':
+ if (strstr(mysql_get_host_info(&mysql),"TCP/IP") ||
+ ! mysql.unix_socket)
+ add_int_to_prompt(mysql.port);
+ else
+ {
+ char *pos=strrchr(mysql.unix_socket,'/');
+ processed_prompt.append(pos ? pos+1 : mysql.unix_socket);
+ }
+ break;
+ case 'U':
+ if (!full_username)
+ init_username();
+ processed_prompt.append(full_username);
+ break;
+ case 'u':
+ if (!full_username)
+ init_username();
+ processed_prompt.append(part_username);
+ break;
+ case PROMPT_CHAR:
+ processed_prompt.append(PROMPT_CHAR);
+ break;
+ case 'n':
+ processed_prompt.append('\n');
+ break;
+ case ' ':
+ case '_':
+ processed_prompt.append(' ');
+ break;
+ case 'R':
+ add_int_to_prompt(t->tm_hour);
+ break;
+ case 'r':
+ int getHour;
+ getHour = t->tm_hour % 12;
+ if (getHour == 0)
+ getHour=12;
+ add_int_to_prompt(getHour);
+ break;
+ case 'm':
+ if (t->tm_min < 10)
+ processed_prompt.append('0');
+ add_int_to_prompt(t->tm_min);
+ break;
+ case 'y':
+ int getYear;
+ getYear = t->tm_year % 100;
+ if (getYear < 10)
+ processed_prompt.append('0');
+ add_int_to_prompt(getYear);
+ break;
+ case 'Y':
+ add_int_to_prompt(t->tm_year+1900);
+ break;
+ case 'D':
+ char* dateTime;
+ time_t lclock;
+ lclock = time(NULL);
+ dateTime = ctime(&lclock);
+ processed_prompt.append(strtok(dateTime,"\n"));
+ break;
+ case 's':
+ add_int_to_prompt(t->tm_sec);
+ break;
+ case 'w':
+ processed_prompt.append(day_names[t->tm_wday]);
+ break;
+ case 'P':
+ processed_prompt.append(t->tm_hour < 12 ? "am" : "pm");
+ break;
+ case 'o':
+ add_int_to_prompt(t->tm_mon+1);
+ break;
+ case 'O':
+ processed_prompt.append(month_names[t->tm_mon]);
+ break;
+ case '\'':
+ processed_prompt.append("'");
+ break;
+ case '"':
+ processed_prompt.append('"');
+ break;
+ case 'S':
+ processed_prompt.append(';');
+ break;
+ case 't':
+ processed_prompt.append('\t');
+ break;
+ default:
+ processed_prompt.append(c);
+ }
+ }
+ }
+ processed_prompt.append('\0');
+ return processed_prompt.ptr();
+}
+
+
+static void add_int_to_prompt(int toadd)
+{
+ char buffer[16];
+ int10_to_str(toadd,buffer,10);
+ processed_prompt.append(buffer);
+}
+
+static void init_username()
+{
+ 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)))
+ {
+ 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
+ }
+}
+
+static int com_prompt(String *buffer, char *line)
+{
+ char *ptr=strchr(line, ' ');
+ prompt_counter = 0;
+ my_free(current_prompt,MYF(MY_ALLOW_ZERO_PTR));
+ current_prompt=my_strdup(ptr ? ptr+1 : default_prompt,MYF(MY_WME));
+ if (!ptr)
+ 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;
+}
+
+#ifndef EMBEDDED_LIBRARY
/* Keep sql_string library happy */
gptr sql_alloc(unsigned int Size)
@@ -2461,3 +2793,4 @@ void sql_element_free(void *ptr)
{
my_free((gptr) ptr,MYF(0));
}
+#endif /* EMBEDDED_LIBRARY */