Skip to content

Commit 4cb27fe

Browse files
committed
o Improve psql's handling of multi-line statements
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
1 parent fbb1dae commit 4cb27fe

File tree

6 files changed

+125
-23
lines changed

6 files changed

+125
-23
lines changed

src/bin/psql/help.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@
33
*
44
* Copyright (c) 2000-2005, PostgreSQL Global Development Group
55
*
6-
* $PostgreSQL: pgsql/src/bin/psql/help.c,v 1.106 2005/10/15 02:49:40 momjian Exp $
6+
* $PostgreSQL: pgsql/src/bin/psql/help.c,v 1.107 2006/02/11 21:55:35 momjian Exp $
77
*/
88
#include "postgres_fe.h"
99
#include "common.h"
10+
#include "pqexpbuffer.h"
1011
#include "input.h"
1112
#include "print.h"
1213
#include "help.h"

src/bin/psql/input.c

Lines changed: 84 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@
33
*
44
* Copyright (c) 2000-2005, PostgreSQL Global Development Group
55
*
6-
* $PostgreSQL: pgsql/src/bin/psql/input.c,v 1.46 2005/10/15 02:49:40 momjian Exp $
6+
* $PostgreSQL: pgsql/src/bin/psql/input.c,v 1.47 2006/02/11 21:55:35 momjian Exp $
77
*/
88
#include "postgres_fe.h"
99

10-
#include "input.h"
1110
#include "pqexpbuffer.h"
11+
#include "input.h"
1212
#include "settings.h"
1313
#include "tab-complete.h"
1414
#include "common.h"
@@ -90,18 +90,55 @@ gets_interactive(const char *prompt)
9090
#ifdef USE_READLINE
9191
char *s;
9292

93-
static char *prev_hist = NULL;
94-
9593
if (useReadline)
9694
/* On some platforms, readline is declared as readline(char *) */
9795
s = readline((char *) prompt);
9896
else
9997
s = gets_basic(prompt);
10098

101-
if (useHistory && s && s[0])
99+
return s;
100+
#else
101+
return gets_basic(prompt);
102+
#endif
103+
}
104+
105+
106+
/* Put the line in the history buffer and also add the trailing \n */
107+
void pgadd_history(char *s, PQExpBuffer history_buf)
108+
{
109+
#ifdef USE_READLINE
110+
111+
int slen;
112+
if (useReadline && useHistory && s && s[0])
102113
{
103-
enum histcontrol HC;
114+
slen = strlen(s);
115+
if (s[slen-1] == '\n')
116+
appendPQExpBufferStr(history_buf, s);
117+
else
118+
{
119+
appendPQExpBufferStr(history_buf, s);
120+
appendPQExpBufferChar(history_buf, '\n');
121+
}
122+
}
123+
#endif
124+
}
104125

126+
127+
/* Feed the contents of the history buffer to readline */
128+
void pgflush_history(PQExpBuffer history_buf)
129+
{
130+
#ifdef USE_READLINE
131+
char *s;
132+
static char *prev_hist;
133+
int slen, i;
134+
135+
if (useReadline && useHistory )
136+
{
137+
enum histcontrol HC;
138+
139+
s = history_buf->data;
140+
prev_hist = NULL;
141+
105142
HC = GetHistControlConfig();
106143

107144
if (((HC & hctl_ignorespace) && s[0] == ' ') ||
@@ -112,17 +149,27 @@ gets_interactive(const char *prompt)
112149
else
113150
{
114151
free(prev_hist);
152+
slen = strlen(s);
153+
/* Trim the trailing \n's */
154+
for (i = slen-1; i >= 0 && s[i] == '\n'; i--)
155+
;
156+
s[i + 1] = '\0';
115157
prev_hist = pg_strdup(s);
116158
add_history(s);
117159
}
160+
161+
resetPQExpBuffer(history_buf);
118162
}
119-
120-
return s;
121-
#else
122-
return gets_basic(prompt);
123163
#endif
124164
}
125165

166+
void pgclear_history(PQExpBuffer history_buf)
167+
{
168+
#ifdef USE_READLINE
169+
if (useReadline && useHistory)
170+
resetPQExpBuffer(history_buf);
171+
#endif
172+
}
126173

127174

128175
/*
@@ -157,6 +204,30 @@ gets_fromFile(FILE *source)
157204
}
158205

159206

207+
static void encode_history()
208+
{
209+
HIST_ENTRY *cur_hist;
210+
char *cur_ptr;
211+
212+
for (history_set_pos(0), cur_hist = current_history();
213+
cur_hist; cur_hist = next_history())
214+
for (cur_ptr = cur_hist->line; *cur_ptr; cur_ptr++)
215+
if (*cur_ptr == '\n')
216+
*cur_ptr = '\0';
217+
}
218+
219+
static void decode_history()
220+
{
221+
HIST_ENTRY *cur_hist;
222+
char *cur_ptr;
223+
224+
for (history_set_pos(0), cur_hist = current_history();
225+
cur_hist; cur_hist = next_history())
226+
for (cur_ptr = cur_hist->line; *cur_ptr; cur_ptr++)
227+
if (*cur_ptr == '\0')
228+
*cur_ptr = '\n';
229+
}
230+
160231

161232
/*
162233
* Put any startup stuff related to input in here. It's good to maintain
@@ -197,6 +268,8 @@ initializeInput(int flags)
197268

198269
if (psql_history)
199270
read_history(psql_history);
271+
272+
decode_history();
200273
}
201274
#endif
202275

@@ -215,6 +288,7 @@ saveHistory(char *fname)
215288
#ifdef USE_READLINE
216289
if (useHistory && fname)
217290
{
291+
encode_history();
218292
if (write_history(fname) == 0)
219293
return true;
220294

src/bin/psql/input.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
*
44
* Copyright (c) 2000-2005, PostgreSQL Global Development Group
55
*
6-
* $PostgreSQL: pgsql/src/bin/psql/input.h,v 1.23 2005/01/01 05:43:08 momjian Exp $
6+
* $PostgreSQL: pgsql/src/bin/psql/input.h,v 1.24 2006/02/11 21:55:35 momjian Exp $
77
*/
88
#ifndef INPUT_H
99
#define INPUT_H
@@ -39,4 +39,9 @@ char *gets_fromFile(FILE *source);
3939
void initializeInput(int flags);
4040
bool saveHistory(char *fname);
4141

42+
void pgadd_history(char *s, PQExpBuffer history_buf);
43+
void pgclear_history(PQExpBuffer history_buf);
44+
void pgflush_history(PQExpBuffer history_buf);
45+
46+
4247
#endif /* INPUT_H */

src/bin/psql/mainloop.c

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
*
44
* Copyright (c) 2000-2005, PostgreSQL Global Development Group
55
*
6-
* $PostgreSQL: pgsql/src/bin/psql/mainloop.c,v 1.69 2005/12/18 02:17:16 petere Exp $
6+
* $PostgreSQL: pgsql/src/bin/psql/mainloop.c,v 1.70 2006/02/11 21:55:35 momjian Exp $
77
*/
88
#include "postgres_fe.h"
99
#include "mainloop.h"
@@ -37,6 +37,7 @@ MainLoop(FILE *source)
3737
PQExpBuffer query_buf; /* buffer for query being accumulated */
3838
PQExpBuffer previous_buf; /* if there isn't anything in the new buffer
3939
* yet, use this one for \e, etc. */
40+
PQExpBuffer history_buf;
4041
char *line; /* current line of input */
4142
int added_nl_pos;
4243
bool success;
@@ -66,7 +67,9 @@ MainLoop(FILE *source)
6667

6768
query_buf = createPQExpBuffer();
6869
previous_buf = createPQExpBuffer();
69-
if (!query_buf || !previous_buf)
70+
history_buf = createPQExpBuffer();
71+
72+
if (!query_buf || !previous_buf || !history_buf)
7073
{
7174
psql_error("out of memory\n");
7275
exit(EXIT_FAILURE);
@@ -90,7 +93,7 @@ MainLoop(FILE *source)
9093
successResult = EXIT_USER;
9194
break;
9295
}
93-
96+
pgclear_history(history_buf);
9497
cancel_pressed = false;
9598
}
9699

@@ -106,6 +109,8 @@ MainLoop(FILE *source)
106109
count_eof = 0;
107110
slashCmdStatus = PSQL_CMD_UNKNOWN;
108111
prompt_status = PROMPT_READY;
112+
if (pset.cur_cmd_interactive)
113+
pgclear_history(history_buf);
109114

110115
if (pset.cur_cmd_interactive)
111116
putc('\n', stdout);
@@ -138,11 +143,15 @@ MainLoop(FILE *source)
138143
psql_scan_reset(scan_state);
139144
slashCmdStatus = PSQL_CMD_UNKNOWN;
140145
prompt_status = PROMPT_READY;
146+
147+
if (pset.cur_cmd_interactive)
148+
/*
149+
* Pass all the contents of history_buf to readline
150+
* and free the history buffer.
151+
*/
152+
pgflush_history(history_buf);
141153
}
142-
143-
/*
144-
* otherwise, get another line
145-
*/
154+
/* otherwise, get another line */
146155
else if (pset.cur_cmd_interactive)
147156
{
148157
/* May need to reset prompt, eg after \r command */
@@ -212,7 +221,11 @@ MainLoop(FILE *source)
212221
*/
213222
psql_scan_setup(scan_state, line, strlen(line));
214223
success = true;
215-
224+
225+
if (pset.cur_cmd_interactive)
226+
/* Put current line in the history buffer */
227+
pgadd_history(line, history_buf);
228+
216229
while (success || !die_on_error)
217230
{
218231
PsqlScanResult scan_result;
@@ -287,6 +300,13 @@ MainLoop(FILE *source)
287300
scan_result == PSCAN_EOL)
288301
break;
289302
}
303+
304+
if (pset.cur_cmd_interactive && prompt_status != PROMPT_CONTINUE)
305+
/*
306+
* Pass all the contents of history_buf to readline
307+
* and free the history buffer.
308+
*/
309+
pgflush_history(history_buf);
290310

291311
psql_scan_finish(scan_state);
292312
free(line);
@@ -333,6 +353,7 @@ MainLoop(FILE *source)
333353

334354
destroyPQExpBuffer(query_buf);
335355
destroyPQExpBuffer(previous_buf);
356+
destroyPQExpBuffer(history_buf);
336357

337358
psql_scan_destroy(scan_state);
338359

src/bin/psql/prompt.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
*
44
* Copyright (c) 2000-2005, PostgreSQL Global Development Group
55
*
6-
* $PostgreSQL: pgsql/src/bin/psql/prompt.c,v 1.41 2006/01/03 23:32:30 tgl Exp $
6+
* $PostgreSQL: pgsql/src/bin/psql/prompt.c,v 1.42 2006/02/11 21:55:35 momjian Exp $
77
*/
88
#include "postgres_fe.h"
99
#include "prompt.h"
@@ -12,6 +12,7 @@
1212

1313
#include "settings.h"
1414
#include "common.h"
15+
#include "pqexpbuffer.h"
1516
#include "input.h"
1617
#include "variables.h"
1718

src/bin/psql/tab-complete.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
*
44
* Copyright (c) 2000-2005, PostgreSQL Global Development Group
55
*
6-
* $PostgreSQL: pgsql/src/bin/psql/tab-complete.c,v 1.144 2006/01/11 08:43:12 neilc Exp $
6+
* $PostgreSQL: pgsql/src/bin/psql/tab-complete.c,v 1.145 2006/02/11 21:55:35 momjian Exp $
77
*/
88

99
/*----------------------------------------------------------------------
@@ -43,14 +43,14 @@
4343

4444
#include "postgres_fe.h"
4545
#include "tab-complete.h"
46+
#include "pqexpbuffer.h"
4647
#include "input.h"
4748

4849
/* If we don't have this, we might as well forget about the whole thing: */
4950
#ifdef USE_READLINE
5051

5152
#include <ctype.h>
5253
#include "libpq-fe.h"
53-
#include "pqexpbuffer.h"
5454
#include "common.h"
5555
#include "settings.h"
5656

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy