This should fix the \e (\p, \g, ...) behaviour on an empty query buffer.
Also, minor tweakage of tab completion, and I hope the output is flushed on time now. -- Peter Eisentraut Sernanders väg 10:115
This commit is contained in:
parent
97dec77fab
commit
77a4729936
|
@ -624,7 +624,7 @@ exec_command(const char *cmd,
|
||||||
|
|
||||||
if (!options[0])
|
if (!options[0])
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Usage \\%s <filename>\n", cmd);
|
fprintf(stderr, "Usage: \\%s <filename>\n", cmd);
|
||||||
success = false;
|
success = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -433,7 +433,6 @@ SendQuery(PsqlSettings *pset, const char *query)
|
||||||
fgets(buf, 3, stdin);
|
fgets(buf, 3, stdin);
|
||||||
if (buf[0] == 'x')
|
if (buf[0] == 'x')
|
||||||
return false;
|
return false;
|
||||||
fflush(stdin);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cancelConn = pset->db;
|
cancelConn = pset->db;
|
||||||
|
@ -479,7 +478,6 @@ SendQuery(PsqlSettings *pset, const char *query)
|
||||||
{
|
{
|
||||||
success = true;
|
success = true;
|
||||||
printQuery(results, &pset->popt, pset->queryFout);
|
printQuery(results, &pset->popt, pset->queryFout);
|
||||||
fflush(pset->queryFout);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case PGRES_EMPTY_QUERY:
|
case PGRES_EMPTY_QUERY:
|
||||||
|
@ -488,10 +486,8 @@ SendQuery(PsqlSettings *pset, const char *query)
|
||||||
case PGRES_COMMAND_OK:
|
case PGRES_COMMAND_OK:
|
||||||
success = true;
|
success = true;
|
||||||
pset->lastOid = PQoidValue(results);
|
pset->lastOid = PQoidValue(results);
|
||||||
if (!GetVariableBool(pset->vars, "quiet")) {
|
if (!GetVariableBool(pset->vars, "quiet"))
|
||||||
fprintf(pset->queryFout, "%s\n", PQcmdStatus(results));
|
fprintf(pset->queryFout, "%s\n", PQcmdStatus(results));
|
||||||
fflush(pset->queryFout);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PGRES_COPY_OUT:
|
case PGRES_COPY_OUT:
|
||||||
|
@ -515,10 +511,11 @@ SendQuery(PsqlSettings *pset, const char *query)
|
||||||
case PGRES_BAD_RESPONSE:
|
case PGRES_BAD_RESPONSE:
|
||||||
success = false;
|
success = false;
|
||||||
fputs(PQerrorMessage(pset->db), pset->queryFout);
|
fputs(PQerrorMessage(pset->db), pset->queryFout);
|
||||||
fflush(pset->queryFout);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fflush(pset->queryFout);
|
||||||
|
|
||||||
if (PQstatus(pset->db) == CONNECTION_BAD)
|
if (PQstatus(pset->db) == CONNECTION_BAD)
|
||||||
{
|
{
|
||||||
fputs("The connection to the server was lost. Attempting reset: ", stderr);
|
fputs("The connection to the server was lost. Attempting reset: ", stderr);
|
||||||
|
@ -541,6 +538,7 @@ SendQuery(PsqlSettings *pset, const char *query)
|
||||||
fprintf(pset->queryFout, "Asynchronous NOTIFY '%s' from backend with pid '%d' received.\n",
|
fprintf(pset->queryFout, "Asynchronous NOTIFY '%s' from backend with pid '%d' received.\n",
|
||||||
notify->relname, notify->be_pid);
|
notify->relname, notify->be_pid);
|
||||||
free(notify);
|
free(notify);
|
||||||
|
fflush(pset->queryFout);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (results)
|
if (results)
|
||||||
|
|
|
@ -32,11 +32,7 @@ gets_interactive(const char *prompt)
|
||||||
|
|
||||||
#ifdef USE_READLINE
|
#ifdef USE_READLINE
|
||||||
if (useReadline)
|
if (useReadline)
|
||||||
{
|
|
||||||
s = readline(prompt);
|
s = readline(prompt);
|
||||||
fputc('\r', stdout);
|
|
||||||
fflush(stdout);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -29,6 +29,8 @@ int
|
||||||
MainLoop(PsqlSettings *pset, FILE *source)
|
MainLoop(PsqlSettings *pset, FILE *source)
|
||||||
{
|
{
|
||||||
PQExpBuffer query_buf; /* buffer for query being accumulated */
|
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. */
|
||||||
char *line; /* current line of input */
|
char *line; /* current line of input */
|
||||||
int len; /* length of the line */
|
int len; /* length of the line */
|
||||||
int successResult = EXIT_SUCCESS;
|
int successResult = EXIT_SUCCESS;
|
||||||
|
@ -63,7 +65,8 @@ MainLoop(PsqlSettings *pset, FILE *source)
|
||||||
|
|
||||||
|
|
||||||
query_buf = createPQExpBuffer();
|
query_buf = createPQExpBuffer();
|
||||||
if (!query_buf)
|
previous_buf = createPQExpBuffer();
|
||||||
|
if (!query_buf || !previous_buf)
|
||||||
{
|
{
|
||||||
perror("createPQExpBuffer");
|
perror("createPQExpBuffer");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
|
@ -80,21 +83,21 @@ MainLoop(PsqlSettings *pset, FILE *source)
|
||||||
{
|
{
|
||||||
if (slashCmdStatus == CMD_NEWEDIT)
|
if (slashCmdStatus == CMD_NEWEDIT)
|
||||||
{
|
{
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* just returned from editing the line? then just copy to the
|
* just returned from editing the line? then just copy to the
|
||||||
* input buffer
|
* input buffer
|
||||||
*/
|
*/
|
||||||
line = strdup(query_buf->data);
|
line = xstrdup(query_buf->data);
|
||||||
resetPQExpBuffer(query_buf);
|
resetPQExpBuffer(query_buf);
|
||||||
/* reset parsing state since we are rescanning whole query */
|
/* reset parsing state since we are rescanning whole line */
|
||||||
xcomment = false;
|
xcomment = false;
|
||||||
in_quote = 0;
|
in_quote = 0;
|
||||||
paren_level = 0;
|
paren_level = 0;
|
||||||
|
slashCmdStatus = CMD_UNKNOWN;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
fflush(stdout);
|
||||||
/*
|
/*
|
||||||
* otherwise, set interactive prompt if necessary and get
|
* otherwise, set interactive prompt if necessary and get
|
||||||
* another line
|
* another line
|
||||||
|
@ -170,8 +173,6 @@ MainLoop(PsqlSettings *pset, FILE *source)
|
||||||
puts(line);
|
puts(line);
|
||||||
|
|
||||||
|
|
||||||
slashCmdStatus = CMD_UNKNOWN;
|
|
||||||
|
|
||||||
len = strlen(line);
|
len = strlen(line);
|
||||||
query_start = 0;
|
query_start = 0;
|
||||||
|
|
||||||
|
@ -275,11 +276,13 @@ MainLoop(PsqlSettings *pset, FILE *source)
|
||||||
/* semicolon? then send query */
|
/* semicolon? then send query */
|
||||||
else if (line[i] == ';' && !was_bslash)
|
else if (line[i] == ';' && !was_bslash)
|
||||||
{
|
{
|
||||||
|
/* delete the old query buffer from last time around */
|
||||||
|
if (slashCmdStatus == CMD_SEND)
|
||||||
|
|
||||||
line[i] = '\0';
|
line[i] = '\0';
|
||||||
/* is there anything else on the line? */
|
/* is there anything else on the line? */
|
||||||
if (line[query_start + strspn(line + query_start, " \t")] != '\0')
|
if (line[query_start + strspn(line + query_start, " \t")] != '\0')
|
||||||
{
|
{
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* insert a cosmetic newline, if this is not the first
|
* insert a cosmetic newline, if this is not the first
|
||||||
* line in the buffer
|
* line in the buffer
|
||||||
|
@ -292,7 +295,10 @@ MainLoop(PsqlSettings *pset, FILE *source)
|
||||||
|
|
||||||
/* execute query */
|
/* execute query */
|
||||||
success = SendQuery(pset, query_buf->data);
|
success = SendQuery(pset, query_buf->data);
|
||||||
|
slashCmdStatus = success ? CMD_SEND : CMD_ERROR;
|
||||||
|
|
||||||
|
resetPQExpBuffer(previous_buf);
|
||||||
|
appendPQExpBufferStr(previous_buf, query_buf->data);
|
||||||
resetPQExpBuffer(query_buf);
|
resetPQExpBuffer(query_buf);
|
||||||
query_start = i + thislen;
|
query_start = i + thislen;
|
||||||
}
|
}
|
||||||
|
@ -316,7 +322,6 @@ MainLoop(PsqlSettings *pset, FILE *source)
|
||||||
/* is there anything else on the line? */
|
/* is there anything else on the line? */
|
||||||
if (line[query_start + strspn(line + query_start, " \t")] != '\0')
|
if (line[query_start + strspn(line + query_start, " \t")] != '\0')
|
||||||
{
|
{
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* insert a cosmetic newline, if this is not the first
|
* insert a cosmetic newline, if this is not the first
|
||||||
* line in the buffer
|
* line in the buffer
|
||||||
|
@ -328,16 +333,26 @@ MainLoop(PsqlSettings *pset, FILE *source)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* handle backslash command */
|
/* handle backslash command */
|
||||||
|
slashCmdStatus = HandleSlashCmds(pset, &line[i],
|
||||||
slashCmdStatus = HandleSlashCmds(pset, &line[i], query_buf, &end_of_cmd);
|
query_buf->len>0 ? query_buf : previous_buf,
|
||||||
|
&end_of_cmd);
|
||||||
|
|
||||||
success = slashCmdStatus != CMD_ERROR;
|
success = slashCmdStatus != CMD_ERROR;
|
||||||
|
|
||||||
|
if ((slashCmdStatus == CMD_SEND || slashCmdStatus == CMD_NEWEDIT) &&
|
||||||
|
query_buf->len == 0) {
|
||||||
|
/* copy previous buffer to current for for handling */
|
||||||
|
appendPQExpBufferStr(query_buf, previous_buf->data);
|
||||||
|
}
|
||||||
|
|
||||||
if (slashCmdStatus == CMD_SEND)
|
if (slashCmdStatus == CMD_SEND)
|
||||||
{
|
{
|
||||||
success = SendQuery(pset, query_buf->data);
|
success = SendQuery(pset, query_buf->data);
|
||||||
resetPQExpBuffer(query_buf);
|
|
||||||
query_start = i + thislen;
|
query_start = i + thislen;
|
||||||
|
|
||||||
|
resetPQExpBuffer(previous_buf);
|
||||||
|
appendPQExpBufferStr(previous_buf, query_buf->data);
|
||||||
|
resetPQExpBuffer(query_buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* is there anything left after the backslash command? */
|
/* is there anything left after the backslash command? */
|
||||||
|
@ -358,13 +373,6 @@ MainLoop(PsqlSettings *pset, FILE *source)
|
||||||
} /* for (line) */
|
} /* for (line) */
|
||||||
|
|
||||||
|
|
||||||
if (!success && die_on_error && !pset->cur_cmd_interactive)
|
|
||||||
{
|
|
||||||
successResult = EXIT_USER;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (slashCmdStatus == CMD_TERMINATE)
|
if (slashCmdStatus == CMD_TERMINATE)
|
||||||
{
|
{
|
||||||
successResult = EXIT_SUCCESS;
|
successResult = EXIT_SUCCESS;
|
||||||
|
@ -387,19 +395,30 @@ MainLoop(PsqlSettings *pset, FILE *source)
|
||||||
if (query_buf->data[0] != '\0' && GetVariableBool(pset->vars, "singleline"))
|
if (query_buf->data[0] != '\0' && GetVariableBool(pset->vars, "singleline"))
|
||||||
{
|
{
|
||||||
success = SendQuery(pset, query_buf->data);
|
success = SendQuery(pset, query_buf->data);
|
||||||
|
slashCmdStatus = success ? CMD_SEND : CMD_ERROR;
|
||||||
|
resetPQExpBuffer(previous_buf);
|
||||||
|
appendPQExpBufferStr(previous_buf, query_buf->data);
|
||||||
resetPQExpBuffer(query_buf);
|
resetPQExpBuffer(query_buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (!success && die_on_error && !pset->cur_cmd_interactive)
|
||||||
|
{
|
||||||
|
successResult = EXIT_USER;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Have we lost the db connection? */
|
/* Have we lost the db connection? */
|
||||||
if (pset->db == NULL && !pset->cur_cmd_interactive)
|
if (pset->db == NULL && !pset->cur_cmd_interactive)
|
||||||
{
|
{
|
||||||
successResult = EXIT_BADCONN;
|
successResult = EXIT_BADCONN;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} /* while */
|
} /* while !EOF */
|
||||||
|
|
||||||
destroyPQExpBuffer(query_buf);
|
destroyPQExpBuffer(query_buf);
|
||||||
|
destroyPQExpBuffer(previous_buf);
|
||||||
|
|
||||||
pset->cur_cmd_source = prev_cmd_source;
|
pset->cur_cmd_source = prev_cmd_source;
|
||||||
pset->cur_cmd_interactive = prev_cmd_interactive;
|
pset->cur_cmd_interactive = prev_cmd_interactive;
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
#include <libpq-fe.h>
|
#include <libpq-fe.h>
|
||||||
#include <postgres_ext.h> /* for Oid type */
|
#include <postgres_ext.h> /* for Oid type */
|
||||||
|
|
||||||
#define DEFAULT_PAGER "/bin/more"
|
#define DEFAULT_PAGER "more"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -325,6 +325,11 @@ print_aligned_vertical(const char *title, const char * const * headers,
|
||||||
dwidth = 0;
|
dwidth = 0;
|
||||||
char *divider;
|
char *divider;
|
||||||
|
|
||||||
|
if (cells[0] == NULL) {
|
||||||
|
puts("(No rows)\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* count columns and find longest header */
|
/* count columns and find longest header */
|
||||||
for (ptr = headers; *ptr; ptr++)
|
for (ptr = headers; *ptr; ptr++)
|
||||||
{
|
{
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
#include "print.h"
|
#include "print.h"
|
||||||
|
|
||||||
#define DEFAULT_FIELD_SEP "|"
|
#define DEFAULT_FIELD_SEP "|"
|
||||||
#define DEFAULT_EDITOR "/bin/vi"
|
#define DEFAULT_EDITOR "vi"
|
||||||
|
|
||||||
#define DEFAULT_PROMPT1 "%/%R%# "
|
#define DEFAULT_PROMPT1 "%/%R%# "
|
||||||
#define DEFAULT_PROMPT2 "%/%R%# "
|
#define DEFAULT_PROMPT2 "%/%R%# "
|
||||||
|
|
|
@ -203,7 +203,7 @@ char ** psql_completion(char *text, int start, int end)
|
||||||
|
|
||||||
(void)end; /* not used */
|
(void)end; /* not used */
|
||||||
|
|
||||||
rl_filename_quoting_desired = 1;
|
rl_completion_append_character = ' ';
|
||||||
|
|
||||||
/* Clear a few things. */
|
/* Clear a few things. */
|
||||||
completion_charp = NULL;
|
completion_charp = NULL;
|
||||||
|
@ -501,6 +501,11 @@ char ** psql_completion(char *text, int start, int end)
|
||||||
COMPLETE_WITH_QUERY(Query_for_list_of_tables);
|
COMPLETE_WITH_QUERY(Query_for_list_of_tables);
|
||||||
|
|
||||||
|
|
||||||
|
/* ... FROM ... */
|
||||||
|
else if (strcasecmp(prev_wd, "FROM") == 0 )
|
||||||
|
COMPLETE_WITH_QUERY(Query_for_list_of_tables);
|
||||||
|
|
||||||
|
|
||||||
/* Backslash commands */
|
/* Backslash commands */
|
||||||
else if (strcmp(prev_wd, "\\connect")==0 || strcmp(prev_wd, "\\c")==0)
|
else if (strcmp(prev_wd, "\\connect")==0 || strcmp(prev_wd, "\\c")==0)
|
||||||
COMPLETE_WITH_QUERY(Query_for_list_of_databases);
|
COMPLETE_WITH_QUERY(Query_for_list_of_databases);
|
||||||
|
@ -510,7 +515,7 @@ char ** psql_completion(char *text, int start, int end)
|
||||||
COMPLETE_WITH_LIST(sql_commands);
|
COMPLETE_WITH_LIST(sql_commands);
|
||||||
else if (strcmp(prev_wd, "\\pset")==0) {
|
else if (strcmp(prev_wd, "\\pset")==0) {
|
||||||
char * my_list[] = { "format", "border", "expanded", "null", "fieldsep",
|
char * my_list[] = { "format", "border", "expanded", "null", "fieldsep",
|
||||||
"tuples_only", "title", "tableattr", "pager" };
|
"tuples_only", "title", "tableattr", "pager", NULL };
|
||||||
COMPLETE_WITH_LIST(my_list);
|
COMPLETE_WITH_LIST(my_list);
|
||||||
}
|
}
|
||||||
else if( strcmp(prev_wd, "\\e")==0 || strcmp(prev_wd, "\\edit")==0 ||
|
else if( strcmp(prev_wd, "\\e")==0 || strcmp(prev_wd, "\\edit")==0 ||
|
||||||
|
@ -541,8 +546,8 @@ char ** psql_completion(char *text, int start, int end)
|
||||||
of default list. If we were to just return NULL, readline automatically
|
of default list. If we were to just return NULL, readline automatically
|
||||||
attempts filename completion, and that's usually no good. */
|
attempts filename completion, and that's usually no good. */
|
||||||
if (matches == NULL) {
|
if (matches == NULL) {
|
||||||
char * my_list[] = { "", "", NULL };
|
COMPLETE_WITH_CONST("");
|
||||||
COMPLETE_WITH_LIST(my_list);
|
rl_completion_append_character = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue