Skip to content

Commit e2e2a9d

Browse files
committed
Code review for psql multiline history patch(es). Fix memory leak,
failure to enter commands in history if canceled by control-C, other infelicities.
1 parent bf64a37 commit e2e2a9d

File tree

7 files changed

+132
-161
lines changed

7 files changed

+132
-161
lines changed

src/bin/psql/command.c

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
*
44
* Copyright (c) 2000-2006, PostgreSQL Global Development Group
55
*
6-
* $PostgreSQL: pgsql/src/bin/psql/command.c,v 1.169 2006/06/07 22:24:45 momjian Exp $
6+
* $PostgreSQL: pgsql/src/bin/psql/command.c,v 1.170 2006/06/11 23:06:00 tgl Exp $
77
*/
88
#include "postgres_fe.h"
99
#include "command.h"
@@ -1361,7 +1361,7 @@ do_edit(const char *filename_arg, PQExpBuffer query_buf)
13611361
}
13621362
else
13631363
{
1364-
/* read file back in */
1364+
/* read file back into query_buf */
13651365
char line[1024];
13661366

13671367
resetPQExpBuffer(query_buf);
@@ -1374,14 +1374,6 @@ do_edit(const char *filename_arg, PQExpBuffer query_buf)
13741374
error = true;
13751375
}
13761376

1377-
#ifdef USE_READLINE
1378-
#ifdef HAVE_REPLACE_HISTORY_ENTRY
1379-
1380-
replace_history_entry(where_history(), query_buf->data, NULL);
1381-
#else
1382-
add_history(query_buf->data);
1383-
#endif
1384-
#endif
13851377
fclose(stream);
13861378
}
13871379

src/bin/psql/help.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,10 @@
33
*
44
* Copyright (c) 2000-2006, PostgreSQL Global Development Group
55
*
6-
* $PostgreSQL: pgsql/src/bin/psql/help.c,v 1.110 2006/03/05 15:58:51 momjian Exp $
6+
* $PostgreSQL: pgsql/src/bin/psql/help.c,v 1.111 2006/06/11 23:06:00 tgl Exp $
77
*/
88
#include "postgres_fe.h"
99
#include "common.h"
10-
#include "pqexpbuffer.h"
1110
#include "input.h"
1211
#include "print.h"
1312
#include "help.h"

src/bin/psql/input.c

Lines changed: 58 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@
33
*
44
* Copyright (c) 2000-2006, PostgreSQL Global Development Group
55
*
6-
* $PostgreSQL: pgsql/src/bin/psql/input.c,v 1.53 2006/03/21 13:38:12 momjian Exp $
6+
* $PostgreSQL: pgsql/src/bin/psql/input.c,v 1.54 2006/06/11 23:06:00 tgl Exp $
77
*/
88
#include "postgres_fe.h"
99

10-
#include "pqexpbuffer.h"
1110
#include "input.h"
11+
#include "pqexpbuffer.h"
1212
#include "settings.h"
1313
#include "tab-complete.h"
1414
#include "common.h"
@@ -78,110 +78,89 @@ GetHistControlConfig(void)
7878
#endif
7979

8080

81-
static char *
82-
gets_basic(const char prompt[])
83-
{
84-
fputs(prompt, stdout);
85-
fflush(stdout);
86-
return gets_fromFile(stdin);
87-
}
88-
89-
9081
/*
9182
* gets_interactive()
9283
*
93-
* Gets a line of interactive input, using readline of desired.
84+
* Gets a line of interactive input, using readline if desired.
9485
* The result is malloc'ed.
9586
*/
9687
char *
9788
gets_interactive(const char *prompt)
9889
{
9990
#ifdef USE_READLINE
100-
char *s;
101-
10291
if (useReadline)
92+
{
10393
/* On some platforms, readline is declared as readline(char *) */
104-
s = readline((char *) prompt);
105-
else
106-
s = gets_basic(prompt);
107-
108-
return s;
109-
#else
110-
return gets_basic(prompt);
94+
return readline((char *) prompt);
95+
}
11196
#endif
97+
98+
fputs(prompt, stdout);
99+
fflush(stdout);
100+
return gets_fromFile(stdin);
112101
}
113102

114103

115-
/* Put the line in the history buffer and also add the trailing \n */
104+
/*
105+
* Append the line to the history buffer, making sure there is a trailing '\n'
106+
*/
116107
void
117-
pg_append_history(char *s, PQExpBuffer history_buf)
108+
pg_append_history(const char *s, PQExpBuffer history_buf)
118109
{
119110
#ifdef USE_READLINE
120-
121-
int slen;
122-
if (useReadline && useHistory && s && s[0])
111+
if (useHistory && s && s[0])
123112
{
124-
slen = strlen(s);
125-
if (s[slen-1] == '\n')
126-
appendPQExpBufferStr(history_buf, s);
127-
else
128-
{
129-
appendPQExpBufferStr(history_buf, s);
113+
appendPQExpBufferStr(history_buf, s);
114+
if (s[strlen(s) - 1] != '\n')
130115
appendPQExpBufferChar(history_buf, '\n');
131-
}
132116
}
133117
#endif
134118
}
135119

136120

137121
/*
138-
* Feed the string to readline
122+
* Emit accumulated history entry to readline's history mechanism,
123+
* then reset the buffer to empty.
124+
*
125+
* Note: we write nothing if history_buf is empty, so extra calls to this
126+
* function don't hurt. There must have been at least one line added by
127+
* pg_append_history before we'll do anything.
139128
*/
140129
void
141-
pg_write_history(char *s)
130+
pg_send_history(PQExpBuffer history_buf)
142131
{
143132
#ifdef USE_READLINE
144-
static char *prev_hist;
145-
int slen, i;
146-
147-
if (useReadline && useHistory )
133+
static char *prev_hist = NULL;
134+
135+
char *s = history_buf->data;
136+
137+
if (useHistory && s[0])
148138
{
149-
enum histcontrol HC;
150-
151-
/* Flushing of empty buffer should do nothing */
152-
if (*s == 0)
153-
return;
154-
155-
prev_hist = NULL;
156-
157-
HC = GetHistControlConfig();
139+
enum histcontrol HC = GetHistControlConfig();
158140

159141
if (((HC & hctl_ignorespace) && s[0] == ' ') ||
160-
((HC & hctl_ignoredups) && prev_hist && strcmp(s, prev_hist) == 0))
142+
((HC & hctl_ignoredups) && prev_hist && strcmp(s, prev_hist) == 0))
161143
{
162144
/* Ignore this line as far as history is concerned */
163145
}
164146
else
165147
{
166-
free(prev_hist);
167-
slen = strlen(s);
168-
/* Trim the trailing \n's */
169-
for (i = slen-1; i >= 0 && s[i] == '\n'; i--)
148+
int i;
149+
150+
/* Trim any trailing \n's (OK to scribble on history_buf) */
151+
for (i = strlen(s)-1; i >= 0 && s[i] == '\n'; i--)
170152
;
171153
s[i + 1] = '\0';
154+
/* Save each previous line for ignoredups processing */
155+
if (prev_hist)
156+
free(prev_hist);
172157
prev_hist = pg_strdup(s);
158+
/* And send it to readline */
173159
add_history(s);
174160
}
175161
}
176-
#endif
177-
}
178162

179-
void
180-
pg_clear_history(PQExpBuffer history_buf)
181-
{
182-
#ifdef USE_READLINE
183-
if (useReadline && useHistory)
184-
resetPQExpBuffer(history_buf);
163+
resetPQExpBuffer(history_buf);
185164
#endif
186165
}
187166

@@ -219,6 +198,9 @@ gets_fromFile(FILE *source)
219198

220199

221200
#ifdef USE_READLINE
201+
/*
202+
* Convert newlines to NL_IN_HISTORY for safe saving in readline history file
203+
*/
222204
static void
223205
encode_history(void)
224206
{
@@ -232,6 +214,9 @@ encode_history(void)
232214
*cur_ptr = NL_IN_HISTORY;
233215
}
234216

217+
/*
218+
* Reverse the above encoding
219+
*/
235220
static void
236221
decode_history(void)
237222
{
@@ -285,9 +270,10 @@ initializeInput(int flags)
285270
}
286271

287272
if (psql_history)
273+
{
288274
read_history(psql_history);
289-
290-
decode_history();
275+
decode_history();
276+
}
291277
}
292278
#endif
293279

@@ -299,11 +285,13 @@ initializeInput(int flags)
299285
}
300286

301287

302-
/* This function is designed for saving the readline history when user
303-
* run \s command or when psql finishes.
304-
* We have an argument named encodeFlag to handle those cases differently
305-
* In that case of call via \s we don't really need to encode \n as \x01,
306-
* but when we save history for Readline we must do that conversion
288+
/*
289+
* This function is for saving the readline history when user
290+
* runs \s command or when psql finishes.
291+
*
292+
* We have an argument named encodeFlag to handle the cases differently.
293+
* In case of call via \s we don't really need to encode \n as \x01,
294+
* but when we save history for Readline we must do that conversion.
307295
*/
308296
bool
309297
saveHistory(char *fname, bool encodeFlag)
@@ -316,7 +304,8 @@ saveHistory(char *fname, bool encodeFlag)
316304
if (write_history(fname) == 0)
317305
return true;
318306

319-
psql_error("could not save history to file \"%s\": %s\n", fname, strerror(errno));
307+
psql_error("could not save history to file \"%s\": %s\n",
308+
fname, strerror(errno));
320309
}
321310
#else
322311
psql_error("history is not supported by this installation\n");

src/bin/psql/input.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
*
44
* Copyright (c) 2000-2006, PostgreSQL Global Development Group
55
*
6-
* $PostgreSQL: pgsql/src/bin/psql/input.h,v 1.27 2006/03/21 13:38:12 momjian Exp $
6+
* $PostgreSQL: pgsql/src/bin/psql/input.h,v 1.28 2006/06/11 23:06:00 tgl Exp $
77
*/
88
#ifndef INPUT_H
99
#define INPUT_H
@@ -32,16 +32,16 @@
3232
#endif
3333
#endif
3434

35+
#include "pqexpbuffer.h"
36+
3537

3638
char *gets_interactive(const char *prompt);
3739
char *gets_fromFile(FILE *source);
3840

3941
void initializeInput(int flags);
4042
bool saveHistory(char *fname, bool encodeFlag);
4143

42-
void pg_append_history(char *s, PQExpBuffer history_buf);
43-
void pg_clear_history(PQExpBuffer history_buf);
44-
void pg_write_history(char *s);
45-
44+
void pg_append_history(const char *s, PQExpBuffer history_buf);
45+
void pg_send_history(PQExpBuffer history_buf);
4646

4747
#endif /* INPUT_H */

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