summaryrefslogtreecommitdiff
path: root/client/mysql.cc
diff options
context:
space:
mode:
authorharrison@corona.lordblink.com <>2004-03-03 15:54:37 -0500
committerharrison@corona.lordblink.com <>2004-03-03 15:54:37 -0500
commitab1786129cdfbaedcdf947d0e24594a41fa28e42 (patch)
tree9081ee0166cb2fa018eec48c5d889ef974d7550e /client/mysql.cc
parent5e360685c15127c353d80cc46f78d818e271239f (diff)
downloadmariadb-git-ab1786129cdfbaedcdf947d0e24594a41fa28e42.tar.gz
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)
Diffstat (limited to 'client/mysql.cc')
-rw-r--r--client/mysql.cc104
1 files changed, 101 insertions, 3 deletions
diff --git a/client/mysql.cc b/client/mysql.cc
index eb466a86c91..5d69d3838ee 100644
--- a/client/mysql.cc
+++ b/client/mysql.cc
@@ -25,7 +25,7 @@
* Matt Wagner <matt@mysql.com>
* Jeremy Cole <jcole@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[]=
{ "server", "embedded", "mysql_SERVER", 0 };
#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 read_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 fix_history(String *final_command);
#endif
static COMMANDS *find_command (char *name,char cmd_name);
@@ -937,7 +952,7 @@ static int read_lines(bool execute_commands)
if (glob_buffer.is_empty()) // If buffer was emptied
in_string=0;
#ifdef HAVE_READLINE
- if (status.add_to_history)
+ if (status.add_to_history && not_in_history(line))
add_history(line);
#endif
continue;
@@ -1014,7 +1029,7 @@ static bool add_line(String &buffer,char *line,char *in_string,
if (!line[0] && buffer.is_empty())
return 0;
#ifdef HAVE_READLINE
- if (status.add_to_history && line[0])
+ if (status.add_to_history && line[0] && not_in_history(line))
add_history(line);
#endif
#ifdef USE_MB
@@ -1169,6 +1184,75 @@ int no_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)
{
/* Allow conditional parsing of the ~/.inputrc file. */
@@ -1631,6 +1715,10 @@ com_help(String *buffer __attribute__((unused)),
static int
com_clear(String *buffer,char *line __attribute__((unused)))
{
+#ifdef HAVE_READLINE
+ if (status.add_to_history)
+ fix_history(buffer);
+#endif
buffer->length(0);
return 0;
}
@@ -1690,6 +1778,16 @@ com_go(String *buffer,char *line __attribute__((unused)))
timer=start_timer();
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)
{
buffer->length(0); // Remove query on error