Fix up history in readline implementation.

Two things changed:
1. Repeated queries are only stored once in the history.
2. Multiline queries are stored in a concated format in the history, 
   in addition to pieces. 
(Push approved by serg)
parent 5e360685
...@@ -36,6 +36,7 @@ guilhem@mysql.com ...@@ -36,6 +36,7 @@ guilhem@mysql.com
gweir@build.mysql.com gweir@build.mysql.com
gweir@work.mysql.com gweir@work.mysql.com
harrison@mysql.com harrison@mysql.com
harry@corona.lordblink.com
heikki@donna.mysql.fi heikki@donna.mysql.fi
heikki@hundin.mysql.fi heikki@hundin.mysql.fi
heikki@rescue. heikki@rescue.
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
* Matt Wagner <matt@mysql.com> * Matt Wagner <matt@mysql.com>
* Jeremy Cole <jcole@mysql.com> * Jeremy Cole <jcole@mysql.com>
* Tonu Samuel <tonu@mysql.com> * Tonu Samuel <tonu@mysql.com>
* Harrison Fisk <hcfisk@buffalo.edu> * Harrison Fisk <harrison@mysql.com>
* *
**/ **/
...@@ -289,10 +289,25 @@ static const char *server_default_groups[]= ...@@ -289,10 +289,25 @@ static const char *server_default_groups[]=
{ "server", "embedded", "mysql_SERVER", 0 }; { "server", "embedded", "mysql_SERVER", 0 };
#ifdef HAVE_READLINE #ifdef HAVE_READLINE
/*
HIST_ENTRY is defined for libedit, but not for the real readline
Need to redefine it for real readline to find it
*/
#if !defined(USE_LIBEDIT_INTERFACE)
typedef struct _hist_entry {
const char *line;
const char *data;
} HIST_ENTRY;
#endif
extern "C" int add_history(const char *command); /* From readline directory */ extern "C" int add_history(const char *command); /* From readline directory */
extern "C" int read_history(const char *command); extern "C" int read_history(const char *command);
extern "C" int write_history(const char *command); extern "C" int write_history(const char *command);
extern "C" HIST_ENTRY *history_get(int num);
extern "C" int history_length;
static int not_in_history(const char *line);
static void initialize_readline (char *name); static void initialize_readline (char *name);
static void fix_history(String *final_command);
#endif #endif
static COMMANDS *find_command (char *name,char cmd_name); static COMMANDS *find_command (char *name,char cmd_name);
...@@ -937,7 +952,7 @@ static int read_lines(bool execute_commands) ...@@ -937,7 +952,7 @@ static int read_lines(bool execute_commands)
if (glob_buffer.is_empty()) // If buffer was emptied if (glob_buffer.is_empty()) // If buffer was emptied
in_string=0; in_string=0;
#ifdef HAVE_READLINE #ifdef HAVE_READLINE
if (status.add_to_history) if (status.add_to_history && not_in_history(line))
add_history(line); add_history(line);
#endif #endif
continue; continue;
...@@ -1014,7 +1029,7 @@ static bool add_line(String &buffer,char *line,char *in_string, ...@@ -1014,7 +1029,7 @@ static bool add_line(String &buffer,char *line,char *in_string,
if (!line[0] && buffer.is_empty()) if (!line[0] && buffer.is_empty())
return 0; return 0;
#ifdef HAVE_READLINE #ifdef HAVE_READLINE
if (status.add_to_history && line[0]) if (status.add_to_history && line[0] && not_in_history(line))
add_history(line); add_history(line);
#endif #endif
#ifdef USE_MB #ifdef USE_MB
...@@ -1169,6 +1184,75 @@ int no_completion() ...@@ -1169,6 +1184,75 @@ int no_completion()
return 0; /* No filename completion */ return 0; /* No filename completion */
} }
/* glues pieces of history back together if in pieces */
static void fix_history(String *final_command)
{
int total_lines = 1;
char *ptr = final_command->c_ptr();
String fixed_buffer; /* Converted buffer */
char str_char = '\0'; /* Character if we are in a string or not */
/* find out how many lines we have and remove newlines */
while (*ptr != '\0')
{
switch (*ptr) {
/* string character */
case '"':
case '\'':
case '`':
if (str_char == '\0') /* open string */
str_char = *ptr;
else if (str_char == *ptr) /* close string */
str_char = '\0';
fixed_buffer.append(ptr,1);
break;
case '\n':
/*
not in string, change to space
if in string, leave it alone
*/
fixed_buffer.append(str_char == '\0' ? " " : "\n");
total_lines++;
break;
case '\\':
fixed_buffer.append('\\');
/* need to see if the backslash is escaping anything */
if (str_char)
{
ptr++;
/* special characters that need escaping */
if (*ptr == '\'' || *ptr == '"' || *ptr == '\\')
fixed_buffer.append(ptr,1);
else
ptr--;
}
break;
default:
fixed_buffer.append(ptr,1);
}
ptr++;
}
if (total_lines > 1)
add_history(fixed_buffer.ptr());
}
/*
returns 0 if line matches the previous history entry
returns 1 if the line doesn't match the previous history entry
*/
static int not_in_history(const char *line)
{
HIST_ENTRY *oldhist = history_get(history_length);
int num;
if (oldhist == 0)
return 1;
if (strcmp(oldhist->line,line) == 0)
return 0;
return 1;
}
static void initialize_readline (char *name) static void initialize_readline (char *name)
{ {
/* Allow conditional parsing of the ~/.inputrc file. */ /* Allow conditional parsing of the ~/.inputrc file. */
...@@ -1631,6 +1715,10 @@ com_help(String *buffer __attribute__((unused)), ...@@ -1631,6 +1715,10 @@ com_help(String *buffer __attribute__((unused)),
static int static int
com_clear(String *buffer,char *line __attribute__((unused))) com_clear(String *buffer,char *line __attribute__((unused)))
{ {
#ifdef HAVE_READLINE
if (status.add_to_history)
fix_history(buffer);
#endif
buffer->length(0); buffer->length(0);
return 0; return 0;
} }
...@@ -1690,6 +1778,16 @@ com_go(String *buffer,char *line __attribute__((unused))) ...@@ -1690,6 +1778,16 @@ com_go(String *buffer,char *line __attribute__((unused)))
timer=start_timer(); timer=start_timer();
error= mysql_real_query_for_lazy(buffer->ptr(),buffer->length()); error= mysql_real_query_for_lazy(buffer->ptr(),buffer->length());
#ifdef HAVE_READLINE
if (status.add_to_history)
{
buffer->append(vertical ? "\\G" : delimiter);
/* Append final command onto history */
fix_history(buffer);
}
#endif
if (error) if (error)
{ {
buffer->length(0); // Remove query on error buffer->length(0); // Remove query on error
......
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