Hello All, 

I'm proposing the small patch for the TODO item -- Improve psql's handling 
of multi-line queries. With this patch the multi-line queries are saved 
by readline as whole and not line by line.

This is my first patch for Postgres but it seems to work and to not break 
anything.

I'm waiting for review, comments, objections, etc...

With Best Regards, 

        Sergey 

*****************************************************
Sergey E. Koposov
Max Planck Institute for Astronomy
Web: http://lnfm1.sai.msu.ru/~math 
E-mail: [EMAIL PROTECTED]

--- pgsql_orig/src/bin/psql/input.c     2005-10-15 04:49:40.000000000 +0200
+++ pgsql/src/bin/psql/input.c  2005-10-30 02:30:05.000000000 +0100
@@ -90,17 +90,57 @@
 #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 */
+char *pgadd_history(char *s, char *history_buf, int *cur_len)
+{
+#ifdef USE_READLINE
+
+       int slen;
+       char *history_buf1;
+       if (useReadline && useHistory && s && s[0])
        {
+               slen = strlen(s);
+               history_buf1 = history_buf;
+               history_buf1 = realloc(history_buf1, (*cur_len + slen + 2) * 
sizeof(char));
+               strcpy(history_buf1 + *cur_len, s);
+               *cur_len += (slen + 1);
+               history_buf1[*cur_len - 1] = '\n';
+               history_buf1[*cur_len] = 0;
+       }       
+       return history_buf1;
+#endif 
+}
+
+/* Feed the contents of the history buffer to readline */
+void pgflush_history(char **history_buf, int *cur_len)
+{
+
+#ifdef USE_READLINE
+       
+       char *s;
+       static char *prev_hist;
+       
+       if (useReadline && useHistory && ((*cur_len) > 0))
+       {
+
                enum histcontrol HC;
+               
+               s = *history_buf;
+               prev_hist = NULL;
+                       
+               s[(*cur_len) - 1] = 0;
 
                HC = GetHistControlConfig();
 
@@ -115,14 +155,14 @@
                        prev_hist = pg_strdup(s);
                        add_history(s);
                }
+               
+               free(s);
+               *history_buf = 0;
+               *cur_len = 0;
        }
-
-       return s;
-#else
-       return gets_basic(prompt);
 #endif
-}
 
+}
 
 
 /*
--- pgsql_orig/src/bin/psql/input.h     2005-01-01 06:43:08.000000000 +0100
+++ pgsql/src/bin/psql/input.h  2005-10-30 02:50:08.000000000 +0200
@@ -39,4 +39,7 @@
 void           initializeInput(int flags);
 bool           saveHistory(char *fname);
 
+char *pgadd_history(char *s, char *history_buf, int *cur_len);
+void pgflush_history(char **history_buf, int *cur_len);
+
 #endif   /* INPUT_H */
--- pgsql_orig/src/bin/psql/mainloop.c  2005-10-15 04:49:40.000000000 +0200
+++ pgsql/src/bin/psql/mainloop.c       2005-10-30 02:32:19.000000000 +0100
@@ -38,6 +38,8 @@
        PQExpBuffer previous_buf;       /* if there isn't anything in the new 
buffer
                                                                 * yet, use 
this one for \e, etc. */
        char       *line;                       /* current line of input */
+       char            *history_buf = 0;
+       int             history_buf_len = 0;
        int                     added_nl_pos;
        bool            success;
        volatile int successResult = EXIT_SUCCESS;
@@ -212,7 +214,13 @@
                 */
                psql_scan_setup(scan_state, line, strlen(line));
                success = true;
-
+               
+               if (pset.cur_cmd_interactive)
+               {
+                       /* Put current line in the history buffer */
+                       history_buf = pgadd_history(line, history_buf, 
&history_buf_len);
+               }
+               
                while (success || !die_on_error)
                {
                        PsqlScanResult scan_result;
@@ -229,6 +237,7 @@
                                (scan_result == PSCAN_EOL &&
                                 GetVariableBool(pset.vars, "SINGLELINE")))
                        {
+                               
                                /* execute query */
                                success = SendQuery(query_buf->data);
                                slashCmdStatus = success ? CMD_SEND : CMD_ERROR;
@@ -249,10 +258,13 @@
                                 * newline again.  This avoids any change to 
query_buf when a
                                 * line contains only a backslash command.
                                 */
+
+
                                if (query_buf->len == added_nl_pos)
                                        query_buf->data[--query_buf->len] = 
'\0';
                                added_nl_pos = -1;
 
+
                                slashCmdStatus = HandleSlashCmds(scan_state,
                                                                                
                 query_buf->len > 0 ?
                                                                                
                 query_buf : previous_buf);
@@ -266,6 +278,7 @@
                                        appendPQExpBufferStr(query_buf, 
previous_buf->data);
                                }
 
+
                                if (slashCmdStatus == CMD_SEND)
                                {
                                        success = SendQuery(query_buf->data);
@@ -287,6 +300,14 @@
                                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, &history_buf_len);
+               }
 
                psql_scan_finish(scan_state);
                free(line);
---------------------------(end of broadcast)---------------------------
TIP 5: don't forget to increase your free space map settings

Reply via email to