Commit 7900c2f1 authored by unknown's avatar unknown

Added --delimiter option to mysql


client/mysql.cc:
  Added --delimiter option to mysql. Statement terminator
  can be a character (';' by default) or a string.
  
  Code clean up
parent 78b2c66b
...@@ -40,4 +40,4 @@ enum options { OPT_CHARSETS_DIR=256, OPT_DEFAULT_CHARSET, ...@@ -40,4 +40,4 @@ enum options { OPT_CHARSETS_DIR=256, OPT_DEFAULT_CHARSET,
OPT_DELETE_MASTER_LOGS, OPT_DELETE_MASTER_LOGS,
OPT_PROMPT, OPT_IGN_LINES,OPT_TRANSACTION,OPT_MYSQL_PROTOCOL, OPT_PROMPT, OPT_IGN_LINES,OPT_TRANSACTION,OPT_MYSQL_PROTOCOL,
OPT_SHARED_MEMORY_BASE_NAME, OPT_FRM, OPT_SKIP_OPTIMIZATION, OPT_SHARED_MEMORY_BASE_NAME, OPT_FRM, OPT_SKIP_OPTIMIZATION,
OPT_COMPATIBLE, OPT_RECONNECT }; OPT_COMPATIBLE, OPT_RECONNECT, OPT_DELIMITER };
...@@ -44,7 +44,7 @@ ...@@ -44,7 +44,7 @@
#include <locale.h> #include <locale.h>
#endif #endif
const char *VER= "13.5"; const char *VER= "14.0";
/* Don't try to make a nice table if the data is too big */ /* Don't try to make a nice table if the data is too big */
#define MAX_COLUMN_LENGTH 1024 #define MAX_COLUMN_LENGTH 1024
...@@ -108,6 +108,7 @@ extern "C" { ...@@ -108,6 +108,7 @@ extern "C" {
#include "completion_hash.h" #include "completion_hash.h"
#define PROMPT_CHAR '\\' #define PROMPT_CHAR '\\'
#define DEFAULT_DELIMITER ";"
typedef struct st_status typedef struct st_status
{ {
...@@ -137,7 +138,7 @@ static uint verbose=0,opt_silent=0,opt_mysql_port=0, opt_local_infile=0; ...@@ -137,7 +138,7 @@ static uint verbose=0,opt_silent=0,opt_mysql_port=0, opt_local_infile=0;
static my_string opt_mysql_unix_port=0; static my_string opt_mysql_unix_port=0;
static int connect_flag=CLIENT_INTERACTIVE; static int connect_flag=CLIENT_INTERACTIVE;
static char *current_host,*current_db,*current_user=0,*opt_password=0, static char *current_host,*current_db,*current_user=0,*opt_password=0,
*current_prompt=0, *current_prompt=0, *delimiter_str= 0,
*default_charset= (char*) MYSQL_CHARSET; *default_charset= (char*) MYSQL_CHARSET;
static char *histfile; static char *histfile;
static String glob_buffer,old_buffer; static String glob_buffer,old_buffer;
...@@ -160,6 +161,8 @@ static char pager[FN_REFLEN], outfile[FN_REFLEN]; ...@@ -160,6 +161,8 @@ static char pager[FN_REFLEN], outfile[FN_REFLEN];
static FILE *PAGER, *OUTFILE; static FILE *PAGER, *OUTFILE;
static MEM_ROOT hash_mem_root; static MEM_ROOT hash_mem_root;
static uint prompt_counter; static uint prompt_counter;
static char delimiter[16]= DEFAULT_DELIMITER;
static uint delimiter_length= 1;
#ifdef HAVE_SMEM #ifdef HAVE_SMEM
static char *shared_memory_base_name=0; static char *shared_memory_base_name=0;
...@@ -187,7 +190,7 @@ static int com_quit(String *str,char*), ...@@ -187,7 +190,7 @@ static int com_quit(String *str,char*),
com_use(String *str,char*), com_source(String *str, char*), com_use(String *str,char*), com_source(String *str, char*),
com_rehash(String *str, char*), com_tee(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*); com_prompt(String *str, char*), com_delimiter(String *str, char*);
#ifdef USE_POPEN #ifdef USE_POPEN
static int com_nopager(String *str, char*), com_pager(String *str, char*), static int com_nopager(String *str, char*), com_pager(String *str, char*),
...@@ -255,7 +258,8 @@ static COMMANDS commands[] = { ...@@ -255,7 +258,8 @@ static COMMANDS commands[] = {
"Set outfile [to_outfile]. Append everything into given outfile." }, "Set outfile [to_outfile]. Append everything into given outfile." },
{ "use", 'u', com_use, 1, { "use", 'u', com_use, 1,
"Use another database. Takes database name as argument." }, "Use another database. Takes database name as argument." },
{ "delimiter", 'd', com_delimiter, 1,
"Set query delimiter. " },
/* Get bash-like expansion for some commands */ /* Get bash-like expansion for some commands */
{ "create table", 0, 0, 0, ""}, { "create table", 0, 0, 0, ""},
{ "create database", 0, 0, 0, ""}, { "create database", 0, 0, 0, ""},
...@@ -313,6 +317,7 @@ int main(int argc,char *argv[]) ...@@ -313,6 +317,7 @@ int main(int argc,char *argv[])
DBUG_ENTER("main"); DBUG_ENTER("main");
DBUG_PROCESS(argv[0]); DBUG_PROCESS(argv[0]);
delimiter_str= delimiter;
default_prompt = my_strdup(getenv("MYSQL_PS1") ? default_prompt = my_strdup(getenv("MYSQL_PS1") ?
getenv("MYSQL_PS1") : getenv("MYSQL_PS1") :
"mysql> ",MYF(MY_WME)); "mysql> ",MYF(MY_WME));
...@@ -482,6 +487,8 @@ static struct my_option my_long_options[] = ...@@ -482,6 +487,8 @@ static struct my_option my_long_options[] =
#endif #endif
{"database", 'D', "Database to use.", (gptr*) &current_db, {"database", 'D', "Database to use.", (gptr*) &current_db,
(gptr*) &current_db, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, (gptr*) &current_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},
{"execute", 'e', "Execute command and quit. (Output like with --batch).", 0, {"execute", 'e', "Execute command and quit. (Output like with --batch).", 0,
0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"vertical", 'E', "Print the output of a query (rows) vertically.", {"vertical", 'E', "Print the output of a query (rows) vertically.",
...@@ -642,6 +649,14 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), ...@@ -642,6 +649,14 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
strmov(mysql_charsets_dir, argument); strmov(mysql_charsets_dir, argument);
charsets_dir = mysql_charsets_dir; charsets_dir = mysql_charsets_dir;
break; break;
case OPT_DELIMITER:
if (argument == disabled_my_option)
strmov(delimiter, DEFAULT_DELIMITER);
else
strmake(delimiter, argument, sizeof(delimiter) - 1);
delimiter_length= strlen(delimiter);
delimiter_str= delimiter;
break;
case OPT_LOCAL_INFILE: case OPT_LOCAL_INFILE:
using_opt_local_infile=1; using_opt_local_infile=1;
break; break;
...@@ -925,7 +940,7 @@ static COMMANDS *find_command (char *name,char cmd_char) ...@@ -925,7 +940,7 @@ static COMMANDS *find_command (char *name,char cmd_char)
{ {
while (my_isspace(charset_info,*name)) while (my_isspace(charset_info,*name))
name++; name++;
if (strchr(name,';') || strstr(name,"\\g")) if (strstr(name, delimiter) || strstr(name, "\\g"))
return ((COMMANDS *) 0); return ((COMMANDS *) 0);
if ((end=strcont(name," \t"))) if ((end=strcont(name," \t")))
{ {
...@@ -958,7 +973,7 @@ static bool add_line(String &buffer,char *line,char *in_string, ...@@ -958,7 +973,7 @@ static bool add_line(String &buffer,char *line,char *in_string,
bool *ml_comment) bool *ml_comment)
{ {
uchar inchar; uchar inchar;
char buff[80],*pos,*out; char buff[80], *pos, *out;
COMMANDS *com; COMMANDS *com;
if (!line[0] && buffer.is_empty()) if (!line[0] && buffer.is_empty())
...@@ -987,7 +1002,9 @@ static bool add_line(String &buffer,char *line,char *in_string, ...@@ -987,7 +1002,9 @@ static bool add_line(String &buffer,char *line,char *in_string,
} }
#endif #endif
if (!*ml_comment && inchar == '\\') if (!*ml_comment && inchar == '\\')
{ // mSQL or postgreSQL style command ? {
// Found possbile one character command like \c
if (!(inchar = (uchar) *++pos)) if (!(inchar = (uchar) *++pos))
break; // readline adds one '\' break; // readline adds one '\'
if (*in_string || inchar == 'N') // \N is short for NULL if (*in_string || inchar == 'N') // \N is short for NULL
...@@ -1004,9 +1021,14 @@ static bool add_line(String &buffer,char *line,char *in_string, ...@@ -1004,9 +1021,14 @@ static bool add_line(String &buffer,char *line,char *in_string,
return 1; // Quit return 1; // Quit
if (com->takes_params) if (com->takes_params)
{ {
for (pos++ ; *pos && *pos != ';' ; pos++) ; // Remove parameters for (pos++ ;
*pos && (*pos != *delimiter ||
!is_prefix(pos + 1, delimiter + 1)) ; pos++)
; // Remove parameters
if (!*pos) if (!*pos)
pos--; pos--;
else
pos+= delimiter_length - 1; // Point at last delim char
} }
out=line; out=line;
} }
...@@ -1020,31 +1042,37 @@ static bool add_line(String &buffer,char *line,char *in_string, ...@@ -1020,31 +1042,37 @@ static bool add_line(String &buffer,char *line,char *in_string,
continue; continue;
} }
} }
else if (!*ml_comment && inchar == ';' && !*in_string)
{ // ';' is end of command else if (!*ml_comment && (*pos == *delimiter &&
is_prefix(pos + 1, delimiter + 1)) &&
!*in_string)
{
uint old_delimiter_length= delimiter_length;
if (out != line) if (out != line)
buffer.append(line,(uint) (out-line)); // Add this line buffer.append(line, (uint) (out - line)); // Add this line
if ((com=find_command(buffer.c_ptr(),0))) if ((com= find_command(buffer.c_ptr(), 0)))
{ {
if ((*com->func)(&buffer,buffer.c_ptr()) > 0) if ((*com->func)(&buffer, buffer.c_ptr()) > 0)
return 1; // Quit return 1; // Quit
} }
else else
{ {
int error=com_go(&buffer,0); int error= com_go(&buffer, 0);
if (error) if (error)
{ {
return error < 0 ? 0 : 1; // < 0 is not fatal return error < 0 ? 0 : 1; // < 0 is not fatal
} }
} }
buffer.length(0); buffer.length(0);
out=line; out= line;
pos+= old_delimiter_length - 1;
} }
else if (!*ml_comment && (!*in_string && (inchar == '#' || else if (!*ml_comment && (!*in_string && (inchar == '#' ||
inchar == '-' && pos[1] == '-' && inchar == '-' && pos[1] == '-' &&
my_isspace(charset_info,pos[2])))) my_isspace(charset_info,pos[2]))))
break; // comment to end of line break; // comment to end of line
else if (!*in_string && inchar == '/' && *(pos+1) == '*' && *(pos+2) != '!') else if (!*in_string && inchar == '/' && *(pos+1) == '*' &&
*(pos+2) != '!')
{ {
pos++; pos++;
*ml_comment= 1; *ml_comment= 1;
...@@ -2353,6 +2381,26 @@ static int com_source(String *buffer, char *line) ...@@ -2353,6 +2381,26 @@ static int com_source(String *buffer, char *line)
} }
/* ARGSUSED */
static int
com_delimiter(String *buffer __attribute__((unused)), char *line)
{
char buff[256], *tmp;
strmake(buff, line, sizeof(buff) - 1);
tmp= get_arg(buff, 0);
if (!tmp || !*tmp)
{
put_info("DELIMITER must be followed by a 'delimiter' character or string",
INFO_ERROR);
return 0;
}
strmake(delimiter, tmp, sizeof(delimiter) - 1);
delimiter_length= strlen(delimiter);
return 0;
}
/* ARGSUSED */ /* ARGSUSED */
static int static int
com_use(String *buffer __attribute__((unused)), char *line) com_use(String *buffer __attribute__((unused)), char *line)
...@@ -2416,16 +2464,15 @@ com_use(String *buffer __attribute__((unused)), char *line) ...@@ -2416,16 +2464,15 @@ com_use(String *buffer __attribute__((unused)), char *line)
char *get_arg(char *line, my_bool get_next_arg) char *get_arg(char *line, my_bool get_next_arg)
{ {
char *ptr; char *ptr, *start;
my_bool quoted= 0, valid_arg= 0; my_bool quoted= 0, valid_arg= 0;
uint count= 0;
char qtype= 0; char qtype= 0;
ptr= line; ptr= line;
if (get_next_arg) if (get_next_arg)
{ {
for (; ptr && *ptr; ptr++); for (; *ptr; ptr++) ;
if ((ptr + 1) && *(ptr + 1)) if (*(ptr + 1))
ptr++; ptr++;
} }
else else
...@@ -2448,18 +2495,12 @@ char *get_arg(char *line, my_bool get_next_arg) ...@@ -2448,18 +2495,12 @@ char *get_arg(char *line, my_bool get_next_arg)
quoted= 1; quoted= 1;
ptr++; ptr++;
} }
for (; ptr && *ptr; ptr++, count++) for (start=ptr ; *ptr; ptr++)
{ {
if (*ptr == '\\') // escaped character if (*ptr == '\\' && ptr[1]) // escaped character
{ {
// jump over the backslash // Remove the backslash
char *tmp_ptr, tmp_buff[256]; strmov(ptr, ptr+1);
tmp_ptr= strmov(tmp_buff, (ptr - count));
tmp_ptr-= (strlen(tmp_buff) - count);
strmov(tmp_ptr, (ptr + 1));
strmov(line, tmp_buff);
ptr= line;
ptr+= count;
} }
else if ((!quoted && *ptr == ' ') || (quoted && *ptr == qtype)) else if ((!quoted && *ptr == ' ') || (quoted && *ptr == qtype))
{ {
...@@ -2467,10 +2508,8 @@ char *get_arg(char *line, my_bool get_next_arg) ...@@ -2467,10 +2508,8 @@ char *get_arg(char *line, my_bool get_next_arg)
break; break;
} }
} }
for (ptr-= count; ptr && *ptr; ptr++) valid_arg= ptr != start;
if (!my_isspace(charset_info, *ptr)) return valid_arg ? start : NullS;
valid_arg= 1;
return valid_arg ? ptr - count : '\0';
} }
...@@ -2512,7 +2551,7 @@ sql_real_connect(char *host,char *database,char *user,char *password, ...@@ -2512,7 +2551,7 @@ sql_real_connect(char *host,char *database,char *user,char *password,
} }
if (!mysql_real_connect(&mysql, host, user, password, if (!mysql_real_connect(&mysql, host, user, password,
database, opt_mysql_port, opt_mysql_unix_port, database, opt_mysql_port, opt_mysql_unix_port,
connect_flag)) connect_flag | CLIENT_MULTI_QUERIES))
{ {
if (!silent || if (!silent ||
(mysql_errno(&mysql) != CR_CONN_HOST_ERROR && (mysql_errno(&mysql) != CR_CONN_HOST_ERROR &&
...@@ -2615,6 +2654,7 @@ com_status(String *buffer __attribute__((unused)), ...@@ -2615,6 +2654,7 @@ com_status(String *buffer __attribute__((unused)),
tee_fprintf(stdout, "Current pager:\t\t%s\n", pager); tee_fprintf(stdout, "Current pager:\t\t%s\n", pager);
tee_fprintf(stdout, "Using outfile:\t\t'%s'\n", opt_outfile ? outfile : ""); tee_fprintf(stdout, "Using outfile:\t\t'%s'\n", opt_outfile ? outfile : "");
#endif #endif
tee_fprintf(stdout, "Using delimiter:\t%s\n", delimiter);
tee_fprintf(stdout, "Server version:\t\t%s\n", mysql_get_server_info(&mysql)); tee_fprintf(stdout, "Server version:\t\t%s\n", mysql_get_server_info(&mysql));
tee_fprintf(stdout, "Protocol version:\t%d\n", mysql_get_proto_info(&mysql)); tee_fprintf(stdout, "Protocol version:\t%d\n", mysql_get_proto_info(&mysql));
tee_fprintf(stdout, "Connection:\t\t%s\n", mysql_get_host_info(&mysql)); tee_fprintf(stdout, "Connection:\t\t%s\n", mysql_get_host_info(&mysql));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment