diff options
Diffstat (limited to 'client/mysql.cc')
-rw-r--r-- | client/mysql.cc | 240 |
1 files changed, 168 insertions, 72 deletions
diff --git a/client/mysql.cc b/client/mysql.cc index 13943691fb4..cef31b46b2c 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2002 MySQL 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 @@ -40,7 +40,7 @@ #include <signal.h> #include <violite.h> -const char *VER= "13.0"; +const char *VER= "13.3"; /* Don't try to make a nice table if the data is too big */ #define MAX_COLUMN_LENGTH 1024 @@ -195,6 +195,7 @@ static void end_pager(); static int init_tee(char *); static void end_tee(); static const char* construct_prompt(); +static char *get_arg(char *line, my_bool get_next_arg); static void init_username(); static void add_int_to_prompt(int toadd); @@ -272,14 +273,15 @@ static const char *server_default_groups[]= { "server", "embedded", "mysql_SERVER", 0 }; #ifdef HAVE_READLINE -extern "C" void add_history(char *command); /* From readline directory */ -extern "C" int read_history(char *command); -extern "C" int write_history(char *command); +extern "C" int add_history(const char *command); /* From readline directory */ +extern "C" int read_history(const char *command); +extern "C" int write_history(const char *command); static void initialize_readline (char *name); #endif static COMMANDS *find_command (char *name,char cmd_name); -static bool add_line(String &buffer,char *line,char *in_string); +static bool add_line(String &buffer,char *line,char *in_string, + bool *ml_comment); static void remove_cntrl(String &buffer); static void print_table_data(MYSQL_RES *result); static void print_table_data_html(MYSQL_RES *result); @@ -387,9 +389,11 @@ int main(int argc,char *argv[]) } } #endif - sprintf(buff, "%s%s", - "Type 'help;' or '\\h' for help. Type '\\c' to clear the buffer.\n", + sprintf(buff, "%s", + "Type 'help;' or '\\h' for help. Type '\\c' to clear the buffer.\n"); +#ifdef NOT_YET "Type 'help [[%]function name[%]]' to get help on usage of function.\n"); +#endif put_info(buff,INFO_INFO); status.exit_status=read_lines(1); // read lines and execute them if (opt_outfile) @@ -661,7 +665,8 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), opt_nopager= 1; case OPT_MYSQL_PROTOCOL: { - if ((opt_protocol = find_type(argument, &sql_protocol_typelib,0)) == ~(ulong) 0) + if ((opt_protocol = find_type(argument, &sql_protocol_typelib,0)) == + ~(ulong) 0) { fprintf(stderr, "Unknown option to protocol: %s\n", argument); exit(1); @@ -804,9 +809,10 @@ static int read_lines(bool execute_commands) char *line; char in_string=0; ulong line_number=0; + bool ml_comment= 0; COMMANDS *com; status.exit_status=1; - + for (;;) { if (status.batch || !execute_commands) @@ -872,7 +878,7 @@ static int read_lines(bool execute_commands) #endif continue; } - if (add_line(glob_buffer,line,&in_string)) + if (add_line(glob_buffer,line,&in_string,&ml_comment)) break; } /* if in batch mode, send last query even if it doesn't end with \g or go */ @@ -933,7 +939,8 @@ static COMMANDS *find_command (char *name,char cmd_char) } -static bool add_line(String &buffer,char *line,char *in_string) +static bool add_line(String &buffer,char *line,char *in_string, + bool *ml_comment) { uchar inchar; char buff[80],*pos,*out; @@ -964,7 +971,7 @@ static bool add_line(String &buffer,char *line,char *in_string) continue; } #endif - if (inchar == '\\') + if (!*ml_comment && inchar == '\\') { // mSQL or postgreSQL style command ? if (!(inchar = (uchar) *++pos)) break; // readline adds one '\' @@ -998,7 +1005,7 @@ static bool add_line(String &buffer,char *line,char *in_string) continue; } } - else if (inchar == ';' && !*in_string) + else if (!*ml_comment && inchar == ';' && !*in_string) { // ';' is end of command if (out != line) buffer.append(line,(uint) (out-line)); // Add this line @@ -1018,17 +1025,33 @@ static bool add_line(String &buffer,char *line,char *in_string) buffer.length(0); out=line; } - else if (!*in_string && (inchar == '#' || - inchar == '-' && pos[1] == '-' && - my_isspace(system_charset_info,pos[2]))) + else if (!*ml_comment && (!*in_string && (inchar == '#' || + inchar == '-' && pos[1] == '-' && + my_isspace(system_charset_info,pos[2])))) break; // comment to end of line + else if (!*in_string && inchar == '/' && *(pos+1) == '*') + { + pos++; + *ml_comment= 1; + if (out != line) + { + buffer.append(line,(uint) (out-line)); + out=line; + } + } + else if (*ml_comment && !*in_string && inchar == '*' && *(pos+1) == '/') + { + pos++; + *ml_comment= 0; + } else { // Add found char to buffer if (inchar == *in_string) *in_string=0; else if (!*in_string && (inchar == '\'' || inchar == '"')) *in_string=(char) inchar; - *out++ = (char) inchar; + if (!(*ml_comment)) + *out++ = (char) inchar; } } if (out != line || !buffer.is_empty()) @@ -1037,7 +1060,7 @@ static bool add_line(String &buffer,char *line,char *in_string) uint length=(uint) (out-line); if (buffer.length() + length >= buffer.alloced_length()) buffer.realloc(buffer.length()+length+IO_SIZE); - if (buffer.append(line,length)) + if (!(*ml_comment) && buffer.append(line,length)) return 1; } return 0; @@ -1058,8 +1081,11 @@ static char **new_mysql_completion (const char *text, int start, int end); if not. */ -char *no_completion (const char *text __attribute__ ((unused)), - int ) +#if defined(USE_NEW_READLINE_INTERFACE) || defined(USE_LIBEDIT_INTERFACE) +char *no_completion(const char*,int) +#else +int no_completion() +#endif { return 0; /* No filename completion */ } @@ -1070,12 +1096,15 @@ static void initialize_readline (char *name) rl_readline_name = name; /* Tell the completer that we want a crack first. */ -#if RL_READLINE_VERSION > 0x0400 - rl_attempted_completion_function = &new_mysql_completion; - rl_completion_entry_function= &no_completion; +#if defined(USE_NEW_READLINE_INTERFACE) + rl_attempted_completion_function= (rl_completion_func_t*)&new_mysql_completion; + rl_completion_entry_function= (rl_compentry_func_t*)&no_completion; +#elif defined(USE_LIBEDIT_INTERFACE) + rl_attempted_completion_function= (CPPFunction*)&new_mysql_completion; + rl_completion_entry_function= (CPFunction*)&no_completion; #else - rl_attempted_completion_function =(CPPFunction *)new_mysql_completion; - rl_completion_entry_function= (Function *)no_completion; + rl_attempted_completion_function= (CPPFunction*)&new_mysql_completion; + rl_completion_entry_function= (Function*)&no_completion; #endif } @@ -1091,7 +1120,7 @@ static char **new_mysql_completion (const char *text, int end __attribute__((unused))) { if (!status.batch && !quick) -#if RL_READLINE_VERSION > 0x0400 +#if defined(USE_NEW_READLINE_INTERFACE) return rl_completion_matches(text, new_command_generator); #else return completion_matches((char *)text, (CPFunction *)new_command_generator); @@ -1279,7 +1308,7 @@ You can turn off this feature to get a quicker startup with -A\n\n"); sizeof(char *) * (num_fields*2+1)))) break; - field_names[i][num_fields*2]='\0'; + field_names[i][num_fields*2]= '\0'; j=0; while ((sql_field=mysql_fetch_field(fields))) { @@ -1299,7 +1328,7 @@ You can turn off this feature to get a quicker startup with -A\n\n"); { tee_fprintf(stdout, "Didn't find any fields in table '%s'\n",table_row[0]); - field_names[i]=0; + field_names[i]= 0; } i++; } @@ -1387,18 +1416,15 @@ static int com_server_help(String *buffer __attribute__((unused)), MYSQL_ROW cur; const char *server_cmd= buffer->ptr(); char cmd_buf[100]; + MYSQL_RES *result; + int error; - if (help_arg[0]!='\'') + if (help_arg[0] != '\'') { - (void*)sprintf(cmd_buf,"help \'%s\';",help_arg); + (void) strxnmov(cmd_buf, sizeof(cmd_buf), "help '", help_arg, "'", NullS); server_cmd= cmd_buf; } - char buff[16], time_buf[32]; - MYSQL_RES *result; - ulong timer; - uint error= 0; - if (!status.batch) { old_buffer= *buffer; @@ -1408,26 +1434,24 @@ static int com_server_help(String *buffer __attribute__((unused)), if (!connected && reconnect()) return 1; - timer= start_timer(); - - error= mysql_real_query_for_lazy(server_cmd,strlen(server_cmd)); - if (error) + if ((error= mysql_real_query_for_lazy(server_cmd,strlen(server_cmd)))) return error; - - error= mysql_store_result_for_lazy(&result); - if (error) + if ((error= mysql_store_result_for_lazy(&result))) return error; if (result) { - int num_rows= mysql_num_rows(result); - if (num_rows==1) + ulonglong num_rows= mysql_num_rows(result); + if (num_rows == 1) { if (!(cur= mysql_fetch_row(result))) - return -1; + { + error= -1; + goto err; + } init_pager(); - if (cur[1][0]=='Y') + if (cur[1][0] == 'Y') { tee_fprintf(PAGER, "\nHelp topic \'%s\'\n", cur[0]); tee_fprintf(PAGER, "%s\n", cur[2]); @@ -1441,17 +1465,19 @@ static int com_server_help(String *buffer __attribute__((unused)), } end_pager(); } - else if (num_rows>1) + else if (num_rows > 1) { put_info("\nMany help items for your request exist", INFO_INFO); put_info("For more specific request please type 'help <item>' where item is one of next :", INFO_INFO); init_pager(); char last_char= '_'; - while ((cur= mysql_fetch_row(result))){ - if (cur[1][0]!=last_char){ + while ((cur= mysql_fetch_row(result))) + { + if (cur[1][0]!=last_char) + { put_info("-------------------------------------------", INFO_INFO); - put_info(cur[1][0]=='Y' ? + put_info(cur[1][0] == 'Y' ? "categories:" : "functions:", INFO_INFO); put_info("-------------------------------------------", INFO_INFO); } @@ -1467,6 +1493,7 @@ static int com_server_help(String *buffer __attribute__((unused)), } } +err: mysql_free_result(result); return error; } @@ -2211,23 +2238,21 @@ com_print(String *buffer,char *line __attribute__((unused))) static int com_connect(String *buffer, char *line) { - char *tmp,buff[256]; + char *tmp, buff[256]; bool save_rehash= rehash; int error; + bzero(buff, sizeof(buff)); if (buffer) { - while (my_isspace(system_charset_info,*line)) - line++; - strnmov(buff,line,sizeof(buff)-1); // Don't destroy history - if (buff[0] == '\\') // Short command - buff[1]=' '; - tmp=(char *) strtok(buff," \t"); // Skip connect command - if (tmp && (tmp=(char *) strtok(NullS," \t;"))) + strmov(buff, line); + tmp= get_arg(buff, 0); + if (tmp && *tmp) { - my_free(current_db,MYF(MY_ALLOW_ZERO_PTR)); - current_db=my_strdup(tmp,MYF(MY_WME)); - if ((tmp=(char *) strtok(NullS," \t;"))) + my_free(current_db, MYF(MY_ALLOW_ZERO_PTR)); + current_db= my_strdup(tmp, MYF(MY_WME)); + tmp= get_arg(buff, 1); + if (tmp) { my_free(current_host,MYF(MY_ALLOW_ZERO_PTR)); current_host=my_strdup(tmp,MYF(MY_WME)); @@ -2313,18 +2338,15 @@ com_use(String *buffer __attribute__((unused)), char *line) char *tmp; char buff[256]; - while (my_isspace(system_charset_info,*line)) - line++; - strnmov(buff,line,sizeof(buff)-1); // Don't destroy history - if (buff[0] == '\\') // Short command - buff[1]=' '; - tmp=(char *) strtok(buff," \t;"); // Skip connect command - if (!tmp || !(tmp=(char *) strtok(NullS," \t;"))) + bzero(buff, sizeof(buff)); + strmov(buff, line); + tmp= get_arg(buff, 0); + if (!tmp || !*tmp) { - put_info("USE must be followed by a database name",INFO_ERROR); + put_info("USE must be followed by a database name", INFO_ERROR); return 0; } - if (!current_db || cmp_database(current_db,tmp)) + if (!current_db || cmp_database(current_db, tmp)) { if (one_database) skip_updates= 1; @@ -2360,6 +2382,75 @@ com_use(String *buffer __attribute__((unused)), char *line) } + +/* + Gets argument from a command on the command line. If get_next_arg is + not defined, skips the command and returns the first argument. The + line is modified by adding zero to the end of the argument. If + get_next_arg is defined, then the function searches for end of string + first, after found, returns the next argument and adds zero to the + end. If you ever wish to use this feature, remember to initialize all + items in the array to zero first. +*/ + +char *get_arg(char *line, my_bool get_next_arg) +{ + char *ptr; + my_bool quoted= 0, valid_arg= 0; + uint count= 0; + char qtype= 0; + + ptr= line; + if (get_next_arg) + { + for (; ptr && *ptr; ptr++); + if ((ptr + 1) && *(ptr + 1)) + ptr++; + } + else + { + /* skip leading white spaces */ + while (my_isspace(system_charset_info, *ptr)) + ptr++; + if (*ptr == '\\') // short command was used + ptr+= 2; + while (!my_isspace(system_charset_info, *ptr)) // skip command + ptr++; + } + while (my_isspace(system_charset_info, *ptr)) + ptr++; + if (*ptr == '\'' || *ptr == '\"' || *ptr == '`') + { + qtype= *ptr; + quoted= 1; + ptr++; + } + for (; ptr && *ptr; ptr++, count++) + { + if (*ptr == '\\') // escaped character + { + // jump over the backslash + char *tmp_ptr, tmp_buff[256]; + 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)) + { + *ptr= 0; + break; + } + } + for (ptr-= count; ptr && *ptr; ptr++) + if (!my_isspace(system_charset_info, *ptr)) + valid_arg= 1; + return valid_arg ? ptr - count : '\0'; +} + + static int sql_real_connect(char *host,char *database,char *user,char *password, uint silent) @@ -2411,7 +2502,9 @@ sql_real_connect(char *host,char *database,char *user,char *password, return -1; // Retryable } connected=1; +#ifndef EMBEDDED_LIBRARY mysql.reconnect=info_flag ? 1 : 0; // We want to know if this happens +#endif #ifdef HAVE_READLINE build_completion_hash(rehash, 1); #endif @@ -2505,12 +2598,14 @@ com_status(String *buffer __attribute__((unused)), tee_fprintf(stdout, "Client characterset:\t%s\n", system_charset_info->name); tee_fprintf(stdout, "Server characterset:\t%s\n", mysql.charset->name); +#ifndef EMBEDDED_LIBRARY if (strstr(mysql_get_host_info(&mysql),"TCP/IP") || ! mysql.unix_socket) tee_fprintf(stdout, "TCP port:\t\t%d\n", mysql.port); else tee_fprintf(stdout, "UNIX socket:\t\t%s\n", mysql.unix_socket); if (mysql.net.compress) tee_fprintf(stdout, "Protocol:\t\tCompressed\n"); +#endif if ((status=mysql_stat(&mysql)) && !mysql_error(&mysql)[0]) { @@ -2776,11 +2871,13 @@ static const char* construct_prompt() break; } case 'p': +#ifndef EMBEDDED_LIBRARY if (strstr(mysql_get_host_info(&mysql),"TCP/IP") || ! mysql.unix_socket) add_int_to_prompt(mysql.port); else processed_prompt.append(strrchr(mysql.unix_socket,'/')+1); +#endif break; case 'U': if (!full_username) @@ -2922,4 +3019,3 @@ void sql_element_free(void *ptr) } #endif /* EMBEDDED_LIBRARY */ - |