mirror of
https://github.com/postgres/postgres.git
synced 2025-05-21 15:54:08 +03:00
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
This commit is contained in:
parent
fbb1daed93
commit
4cb27fef0a
@ -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"
|
||||
|
@ -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])
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
return s;
|
||||
#else
|
||||
return gets_basic(prompt);
|
||||
resetPQExpBuffer(history_buf);
|
||||
}
|
||||
#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;
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
* otherwise, get another line
|
||||
*/
|
||||
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)
|
||||
{
|
||||
/* May need to reset prompt, eg after \r command */
|
||||
@ -213,6 +222,10 @@ 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;
|
||||
@ -288,6 +301,13 @@ MainLoop(FILE *source)
|
||||
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);
|
||||
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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"
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user