I have applied the following patch which saves psql history for
backslash commands used in multi-line statements before the command,
rather than inside it, e.g:

        test=> SELECT
        test-> \d
        No relations found.
        test-> 1;
         ?column?
        ----------
                1
        (1 row)

has history in this order:
        
        test=> \d
        No relations found.
        test=> SELECT
        1;
         ?column?
        ----------
                1
        (1 row)
        
I also renamed some of the history functions for clarity.

---------------------------------------------------------------------------

Sergey E. Koposov wrote:
> Fix of several issues:
> 
> 1) Fix the problems with the \s command. 
> When the saveHistory is executed by the \s command we must not do the 
> conversion \n -> \x01  (per 
> http://archives.postgresql.org/pgsql-hackers/2006-03/msg00317.php )
> 
> 2) Fix the handling of Ctrl+C
> 
> Now when you do
> wsdb=# select 'your long query here '
> wsdb-# 
> and press afterwards the CtrlC the line "select 'your long query here '" 
> will be in the history
> 
> (partly per 
> http://archives.postgresql.org/pgsql-hackers/2006-03/msg00297.php )
> 
> 3) Fix the handling of commands with not closed brackets, quotes, double 
> quotes. (now those commands are not splitted in parts...)
> 
> 4) Fix the behaviour when SINGLELINE mode is used. (before it was almost 
> broken ;( 
> 
> Regards,
>       Sergey
> 
> *****************************************************
> Sergey E. Koposov
> Max Planck Institute for Astronomy
> Web: http://lnfm1.sai.msu.ru/~math 
> E-mail: [EMAIL PROTECTED]
> 
> 
> 

Content-Description: 

[ Attachment, skipping... ]

> 
> ---------------------------(end of broadcast)---------------------------
> TIP 5: don't forget to increase your free space map settings

-- 
  Bruce Momjian   http://candle.pha.pa.us
  SRA OSS, Inc.   http://www.sraoss.com

  + If your life is a hard drive, Christ can be your backup. +
Index: src/bin/psql/input.c
===================================================================
RCS file: /cvsroot/pgsql/src/bin/psql/input.c,v
retrieving revision 1.51
diff -c -c -r1.51 input.c
*** src/bin/psql/input.c        5 Mar 2006 15:58:51 -0000       1.51
--- src/bin/psql/input.c        6 Mar 2006 02:38:05 -0000
***************
*** 114,120 ****
  
  /* Put the line in the history buffer and also add the trailing \n */
  void
! pgadd_history(char *s, PQExpBuffer history_buf)
  {
  #ifdef USE_READLINE
  
--- 114,120 ----
  
  /* Put the line in the history buffer and also add the trailing \n */
  void
! pg_append_history(char *s, PQExpBuffer history_buf)
  {
  #ifdef USE_READLINE
  
***************
*** 134,145 ****
  }
  
  
! /* 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;
        
--- 134,146 ----
  }
  
  
! /*
!  *    Feed the string to readline
!  */
  void
! pg_write_history(char *s)
  {
! #ifdef USE_READLINE
        static char *prev_hist;
        int slen, i;
        
***************
*** 147,153 ****
        {
                enum histcontrol HC;
                
-               s = history_buf->data;
                prev_hist = NULL;
                        
                HC = GetHistControlConfig();
--- 148,153 ----
***************
*** 168,181 ****
                        prev_hist = pg_strdup(s);
                        add_history(s);
                }
-               
-               resetPQExpBuffer(history_buf);
        }
  #endif
  }
  
  void
! pgclear_history(PQExpBuffer history_buf)
  {
  #ifdef USE_READLINE   
        if (useReadline && useHistory)
--- 168,179 ----
                        prev_hist = pg_strdup(s);
                        add_history(s);
                }
        }
  #endif
  }
  
  void
! pg_clear_history(PQExpBuffer history_buf)
  {
  #ifdef USE_READLINE   
        if (useReadline && useHistory)
Index: src/bin/psql/input.h
===================================================================
RCS file: /cvsroot/pgsql/src/bin/psql/input.h,v
retrieving revision 1.25
diff -c -c -r1.25 input.h
*** src/bin/psql/input.h        5 Mar 2006 15:58:51 -0000       1.25
--- src/bin/psql/input.h        6 Mar 2006 02:38:05 -0000
***************
*** 39,47 ****
  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 */
--- 39,47 ----
  void          initializeInput(int flags);
  bool          saveHistory(char *fname);
  
! void pg_append_history(char *s, PQExpBuffer history_buf);
! void pg_clear_history(PQExpBuffer history_buf);
! void pg_write_history(char *s);
  
  
  #endif   /* INPUT_H */
Index: src/bin/psql/mainloop.c
===================================================================
RCS file: /cvsroot/pgsql/src/bin/psql/mainloop.c,v
retrieving revision 1.71
diff -c -c -r1.71 mainloop.c
*** src/bin/psql/mainloop.c     5 Mar 2006 15:58:51 -0000       1.71
--- src/bin/psql/mainloop.c     6 Mar 2006 02:38:05 -0000
***************
*** 41,46 ****
--- 41,48 ----
        char       *line;                       /* current line of input */
        int                     added_nl_pos;
        bool            success;
+       bool            first_query_scan;
+       
        volatile int successResult = EXIT_SUCCESS;
        volatile backslashResult slashCmdStatus = PSQL_CMD_UNKNOWN;
        volatile promptStatus_t prompt_status = PROMPT_READY;
***************
*** 93,99 ****
                                successResult = EXIT_USER;
                                break;
                        }
!                       pgclear_history(history_buf);                   
                        cancel_pressed = false;
                }
  
--- 95,101 ----
                                successResult = EXIT_USER;
                                break;
                        }
!                       pg_clear_history(history_buf);                  
                        cancel_pressed = false;
                }
  
***************
*** 110,116 ****
                        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);
--- 112,118 ----
                        slashCmdStatus = PSQL_CMD_UNKNOWN;
                        prompt_status = PROMPT_READY;
                        if (pset.cur_cmd_interactive)
!                               pg_clear_history(history_buf);                  
  
                        if (pset.cur_cmd_interactive)
                                putc('\n', stdout);
***************
*** 145,155 ****
                        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 */
                else if (pset.cur_cmd_interactive)
--- 147,160 ----
                        prompt_status = PROMPT_READY;
                        
                        if (pset.cur_cmd_interactive)
+                       {
                                /*
                                 *      Pass all the contents of history_buf to 
readline
                                 *      and free the history buffer.
                                 */
!                               pg_write_history(history_buf->data);
!                               pg_clear_history(history_buf);
!                       }
                }
                /* otherwise, get another line */
                else if (pset.cur_cmd_interactive)
***************
*** 221,230 ****
                 */
                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)
                {
--- 226,232 ----
                 */
                psql_scan_setup(scan_state, line, strlen(line));
                success = true;
!               first_query_scan = true;
                
                while (success || !die_on_error)
                {
***************
*** 235,240 ****
--- 237,259 ----
                        prompt_status = prompt_tmp;
  
                        /*
+                        *      If we append to history a backslash command 
that is inside
+                        *      a multi-line query, then when we recall the 
history, the
+                        *      backslash command will make the query invalid, 
so we write
+                        *      backslash commands immediately rather than 
keeping them
+                        *      as part of the current multi-line query.
+                        */
+                       if (first_query_scan && pset.cur_cmd_interactive)
+                       {
+                               if (scan_result == PSCAN_BACKSLASH && 
query_buf->len != 0)
+                                       pg_write_history(line);
+                               else
+                                       pg_append_history(line, history_buf);
+                       }
+                               
+                       first_query_scan = false;
+                       
+                       /*
                         * Send command if semicolon found, or if end of line 
and we're in
                         * single-line mode.
                         */
***************
*** 302,312 ****
                }
                
                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);
--- 321,334 ----
                }
                
                if (pset.cur_cmd_interactive && prompt_status != 
PROMPT_CONTINUE)
+               {
                        /*
                         *      Pass all the contents of history_buf to readline
                         *      and free the history buffer.
                         */
!                       pg_write_history(history_buf->data);
!                       pg_clear_history(history_buf);
!               }
  
                psql_scan_finish(scan_state);
                free(line);
---------------------------(end of broadcast)---------------------------
TIP 9: In versions below 8.0, the planner will ignore your desire to
       choose an index scan if your joining column's datatypes do not
       match

Reply via email to