OSDN Git Service

o Improve psql's handling of multi-line statements
authorBruce Momjian <bruce@momjian.us>
Sat, 11 Feb 2006 21:55:35 +0000 (21:55 +0000)
committerBruce Momjian <bruce@momjian.us>
Sat, 11 Feb 2006 21:55:35 +0000 (21:55 +0000)
Currently, while \e saves a single statement as one entry, interactive
statements are saved one line at a time.  Ideally all statements
would be saved like \e does.

Sergey E. Koposov

src/bin/psql/help.c
src/bin/psql/input.c
src/bin/psql/input.h
src/bin/psql/mainloop.c
src/bin/psql/prompt.c
src/bin/psql/tab-complete.c

index 879cdec..59c8617 100644 (file)
@@ -3,10 +3,11 @@
  *
  * Copyright (c) 2000-2005, PostgreSQL Global Development Group
  *
- * $PostgreSQL: pgsql/src/bin/psql/help.c,v 1.106 2005/10/15 02:49:40 momjian Exp $
+ * $PostgreSQL: pgsql/src/bin/psql/help.c,v 1.107 2006/02/11 21:55:35 momjian Exp $
  */
 #include "postgres_fe.h"
 #include "common.h"
+#include "pqexpbuffer.h"
 #include "input.h"
 #include "print.h"
 #include "help.h"
index 4272fcb..1b6e48c 100644 (file)
@@ -3,12 +3,12 @@
  *
  * Copyright (c) 2000-2005, PostgreSQL Global Development Group
  *
- * $PostgreSQL: pgsql/src/bin/psql/input.c,v 1.46 2005/10/15 02:49:40 momjian Exp $
+ * $PostgreSQL: pgsql/src/bin/psql/input.c,v 1.47 2006/02/11 21:55:35 momjian Exp $
  */
 #include "postgres_fe.h"
 
-#include "input.h"
 #include "pqexpbuffer.h"
+#include "input.h"
 #include "settings.h"
 #include "tab-complete.h"
 #include "common.h"
@@ -90,18 +90,55 @@ gets_interactive(const char *prompt)
 #ifdef USE_READLINE
        char       *s;
 
-       static char *prev_hist = NULL;
-
        if (useReadline)
                /* On some platforms, readline is declared as readline(char *) */
                s = readline((char *) prompt);
        else
                s = gets_basic(prompt);
 
-       if (useHistory && s && s[0])
+       return s;
+#else
+       return gets_basic(prompt);
+#endif
+}
+
+
+/* Put the line in the history buffer and also add the trailing \n */
+void pgadd_history(char *s, PQExpBuffer history_buf)
+{
+#ifdef USE_READLINE
+
+       int slen;
+       if (useReadline && useHistory && s && s[0])
        {
-               enum histcontrol HC;
+               slen = strlen(s);
+               if (s[slen-1] == '\n')
+                       appendPQExpBufferStr(history_buf, s);
+               else
+               {
+                       appendPQExpBufferStr(history_buf, s);
+                       appendPQExpBufferChar(history_buf, '\n');
+               }
+       }       
+#endif 
+}
 
+
+/* Feed the contents of the history buffer to readline */
+void pgflush_history(PQExpBuffer history_buf)
+{
+#ifdef USE_READLINE    
+       char *s;
+       static char *prev_hist;
+       int slen, i;
+       
+       if (useReadline && useHistory )
+       {
+               enum histcontrol HC;
+               
+               s = history_buf->data;
+               prev_hist = NULL;
+                       
                HC = GetHistControlConfig();
 
                if (((HC & hctl_ignorespace) && s[0] == ' ') ||
@@ -112,17 +149,27 @@ gets_interactive(const char *prompt)
                else
                {
                        free(prev_hist);
+                       slen = strlen(s);
+                       /* Trim the trailing \n's */
+                       for (i = slen-1; i >= 0 && s[i] == '\n'; i--)
+                               ;
+                       s[i + 1] = '\0';
                        prev_hist = pg_strdup(s);
                        add_history(s);
                }
+               
+               resetPQExpBuffer(history_buf);
        }
-
-       return s;
-#else
-       return gets_basic(prompt);
 #endif
 }
 
+void pgclear_history(PQExpBuffer history_buf)
+{
+#ifdef USE_READLINE    
+       if (useReadline && useHistory)
+               resetPQExpBuffer(history_buf);
+#endif
+}
 
 
 /*
@@ -157,6 +204,30 @@ gets_fromFile(FILE *source)
 }
 
 
+static void encode_history()
+{
+       HIST_ENTRY *cur_hist;
+       char *cur_ptr;
+
+       for (history_set_pos(0), cur_hist = current_history();
+                cur_hist; cur_hist = next_history())
+               for (cur_ptr = cur_hist->line; *cur_ptr; cur_ptr++)
+                       if (*cur_ptr == '\n')
+                               *cur_ptr = '\0';
+}
+
+static void decode_history()
+{
+       HIST_ENTRY *cur_hist;
+       char *cur_ptr;
+
+       for (history_set_pos(0), cur_hist = current_history();
+                cur_hist; cur_hist = next_history())
+               for (cur_ptr = cur_hist->line; *cur_ptr; cur_ptr++)
+                       if (*cur_ptr == '\0')
+                               *cur_ptr = '\n';
+}
+
 
 /*
  * Put any startup stuff related to input in here. It's good to maintain
@@ -197,6 +268,8 @@ initializeInput(int flags)
 
                if (psql_history)
                        read_history(psql_history);
+                       
+               decode_history();
        }
 #endif
 
@@ -215,6 +288,7 @@ saveHistory(char *fname)
 #ifdef USE_READLINE
        if (useHistory && fname)
        {
+               encode_history();               
                if (write_history(fname) == 0)
                        return true;
 
index bddc174..bd4ed99 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 2000-2005, PostgreSQL Global Development Group
  *
- * $PostgreSQL: pgsql/src/bin/psql/input.h,v 1.23 2005/01/01 05:43:08 momjian Exp $
+ * $PostgreSQL: pgsql/src/bin/psql/input.h,v 1.24 2006/02/11 21:55:35 momjian Exp $
  */
 #ifndef INPUT_H
 #define INPUT_H
@@ -39,4 +39,9 @@ char     *gets_fromFile(FILE *source);
 void           initializeInput(int flags);
 bool           saveHistory(char *fname);
 
+void pgadd_history(char *s, PQExpBuffer history_buf);
+void pgclear_history(PQExpBuffer history_buf);
+void pgflush_history(PQExpBuffer history_buf);
+
+
 #endif   /* INPUT_H */
index cebeda7..00b7969 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 2000-2005, PostgreSQL Global Development Group
  *
- * $PostgreSQL: pgsql/src/bin/psql/mainloop.c,v 1.69 2005/12/18 02:17:16 petere Exp $
+ * $PostgreSQL: pgsql/src/bin/psql/mainloop.c,v 1.70 2006/02/11 21:55:35 momjian Exp $
  */
 #include "postgres_fe.h"
 #include "mainloop.h"
@@ -37,6 +37,7 @@ MainLoop(FILE *source)
        PQExpBuffer query_buf;          /* buffer for query being accumulated */
        PQExpBuffer previous_buf;       /* if there isn't anything in the new buffer
                                                                 * yet, use this one for \e, etc. */
+       PQExpBuffer history_buf;
        char       *line;                       /* current line of input */
        int                     added_nl_pos;
        bool            success;
@@ -66,7 +67,9 @@ MainLoop(FILE *source)
 
        query_buf = createPQExpBuffer();
        previous_buf = createPQExpBuffer();
-       if (!query_buf || !previous_buf)
+       history_buf = createPQExpBuffer();
+
+       if (!query_buf || !previous_buf || !history_buf)
        {
                psql_error("out of memory\n");
                exit(EXIT_FAILURE);
@@ -90,7 +93,7 @@ MainLoop(FILE *source)
                                successResult = EXIT_USER;
                                break;
                        }
-
+                       pgclear_history(history_buf);                   
                        cancel_pressed = false;
                }
 
@@ -106,6 +109,8 @@ MainLoop(FILE *source)
                        count_eof = 0;
                        slashCmdStatus = PSQL_CMD_UNKNOWN;
                        prompt_status = PROMPT_READY;
+                       if (pset.cur_cmd_interactive)
+                               pgclear_history(history_buf);                   
 
                        if (pset.cur_cmd_interactive)
                                putc('\n', stdout);
@@ -138,11 +143,15 @@ MainLoop(FILE *source)
                        psql_scan_reset(scan_state);
                        slashCmdStatus = PSQL_CMD_UNKNOWN;
                        prompt_status = PROMPT_READY;
+                       
+                       if (pset.cur_cmd_interactive)
+                               /*
+                                *      Pass all the contents of history_buf to readline
+                                *      and free the history buffer.
+                                */
+                               pgflush_history(history_buf);
                }
-
-               /*
-                * otherwise, get another line
-                */
+               /* otherwise, get another line */
                else if (pset.cur_cmd_interactive)
                {
                        /* May need to reset prompt, eg after \r command */
@@ -212,7 +221,11 @@ MainLoop(FILE *source)
                 */
                psql_scan_setup(scan_state, line, strlen(line));
                success = true;
-
+               
+               if (pset.cur_cmd_interactive)
+                       /* Put current line in the history buffer */
+                       pgadd_history(line, history_buf);
+               
                while (success || !die_on_error)
                {
                        PsqlScanResult scan_result;
@@ -287,6 +300,13 @@ MainLoop(FILE *source)
                                scan_result == PSCAN_EOL)
                                break;
                }
+               
+               if (pset.cur_cmd_interactive && prompt_status != PROMPT_CONTINUE)
+                       /*
+                        *      Pass all the contents of history_buf to readline
+                        *      and free the history buffer.
+                        */
+                       pgflush_history(history_buf);
 
                psql_scan_finish(scan_state);
                free(line);
@@ -333,6 +353,7 @@ MainLoop(FILE *source)
 
        destroyPQExpBuffer(query_buf);
        destroyPQExpBuffer(previous_buf);
+       destroyPQExpBuffer(history_buf);
 
        psql_scan_destroy(scan_state);
 
index 5afbfc6..f56ce6b 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 2000-2005, PostgreSQL Global Development Group
  *
- * $PostgreSQL: pgsql/src/bin/psql/prompt.c,v 1.41 2006/01/03 23:32:30 tgl Exp $
+ * $PostgreSQL: pgsql/src/bin/psql/prompt.c,v 1.42 2006/02/11 21:55:35 momjian Exp $
  */
 #include "postgres_fe.h"
 #include "prompt.h"
@@ -12,6 +12,7 @@
 
 #include "settings.h"
 #include "common.h"
+#include "pqexpbuffer.h"
 #include "input.h"
 #include "variables.h"
 
index 1a99dc9..fd32a52 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 2000-2005, PostgreSQL Global Development Group
  *
- * $PostgreSQL: pgsql/src/bin/psql/tab-complete.c,v 1.144 2006/01/11 08:43:12 neilc Exp $
+ * $PostgreSQL: pgsql/src/bin/psql/tab-complete.c,v 1.145 2006/02/11 21:55:35 momjian Exp $
  */
 
 /*----------------------------------------------------------------------
@@ -43,6 +43,7 @@
 
 #include "postgres_fe.h"
 #include "tab-complete.h"
+#include "pqexpbuffer.h"
 #include "input.h"
 
 /* If we don't have this, we might as well forget about the whole thing: */
@@ -50,7 +51,6 @@
 
 #include <ctype.h>
 #include "libpq-fe.h"
-#include "pqexpbuffer.h"
 #include "common.h"
 #include "settings.h"