Commit add932ee authored by Bruce Momjian's avatar Bruce Momjian

I'm continuing to work on cleaning up code in psql. As things appear

now, my changes seem to work.  Some possible minor bugs got squished
on the way but I can't be sure without more feedback from people who
really put the code to the test.

The new patch mostly simplifies variable handling and reduces code
duplication.  Changes in the command parser eliminate some redundant
variables (boolean state + depth counter), replaces some
"else if" constructs with switches, and so on.  It is meant to be
applied together with my previous patch, although I hope they don't
conflict; I went back to the CVS version for this one.

One more thing I thought should perhaps be changed: an IGNOREEOF
value of n will ignore only n-1 EOFs.  I didn't want to touch this
for fear of breaking existing applications, but it does seem a tad
illogical.

Jeroen T. Vermeulen
parent 1b3d4cef
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* *
* Copyright 2000-2002 by PostgreSQL Global Development Group * Copyright 2000-2002 by PostgreSQL Global Development Group
* *
* $Header: /cvsroot/pgsql/src/bin/psql/command.c,v 1.93 2003/03/19 22:49:43 momjian Exp $ * $Header: /cvsroot/pgsql/src/bin/psql/command.c,v 1.94 2003/03/20 06:43:35 momjian Exp $
*/ */
#include "postgres_fe.h" #include "postgres_fe.h"
#include "command.h" #include "command.h"
...@@ -669,15 +669,7 @@ exec_command(const char *cmd, ...@@ -669,15 +669,7 @@ exec_command(const char *cmd,
if (!opt0) if (!opt0)
{ {
/* list all variables */ /* list all variables */
PrintVariables(pset.vars);
/*
* XXX This is in utter violation of the GetVariable
* abstraction, but I have not bothered to do it better.
*/
struct _variable *ptr;
for (ptr = pset.vars; ptr->next; ptr = ptr->next)
fprintf(stdout, "%s = '%s'\n", ptr->next->name, ptr->next->value);
success = true; success = true;
} }
else else
...@@ -1073,9 +1065,7 @@ scan_option(char **string, enum option_type type, char *quote, bool semicolon) ...@@ -1073,9 +1065,7 @@ scan_option(char **string, enum option_type type, char *quote, bool semicolon)
save_char = options_string[pos + token_end + 1]; save_char = options_string[pos + token_end + 1];
options_string[pos + token_end + 1] = '\0'; options_string[pos + token_end + 1] = '\0';
value = GetVariable(pset.vars, options_string + pos + 1); value = GetVariable(pset.vars, options_string + pos + 1);
if (!value) return_val = xstrdup(value ? value : "");
value = "";
return_val = xstrdup(value);
options_string[pos + token_end + 1] = save_char; options_string[pos + token_end + 1] = save_char;
*string = &options_string[pos + token_end + 1]; *string = &options_string[pos + token_end + 1];
/* XXX should we set *quote to ':' here? */ /* XXX should we set *quote to ':' here? */
...@@ -1287,15 +1277,9 @@ unescape(const unsigned char *source, size_t len) ...@@ -1287,15 +1277,9 @@ unescape(const unsigned char *source, size_t len)
case '7': case '7':
case '8': case '8':
case '9': case '9':
{ c = parse_char((char **)&p);
long int l;
char *end;
l = strtol(p, &end, 0);
c = (char) l;
p = end - 1;
break; break;
}
default: default:
c = *p; c = *p;
} }
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* *
* Copyright 2000 by PostgreSQL Global Development Group * Copyright 2000 by PostgreSQL Global Development Group
* *
* $Header: /cvsroot/pgsql/src/bin/psql/common.c,v 1.59 2003/03/20 06:00:12 momjian Exp $ * $Header: /cvsroot/pgsql/src/bin/psql/common.c,v 1.60 2003/03/20 06:43:35 momjian Exp $
*/ */
#include "postgres_fe.h" #include "postgres_fe.h"
#include "common.h" #include "common.h"
...@@ -368,7 +368,7 @@ PSQLexec(const char *query, bool ignore_command_ok) ...@@ -368,7 +368,7 @@ PSQLexec(const char *query, bool ignore_command_ok)
{ {
PGresult *res = NULL; PGresult *res = NULL;
PGresult *newres; PGresult *newres;
const char *var; int echo_hidden;
ExecStatusType rstatus; ExecStatusType rstatus;
if (!pset.db) if (!pset.db)
...@@ -377,17 +377,17 @@ PSQLexec(const char *query, bool ignore_command_ok) ...@@ -377,17 +377,17 @@ PSQLexec(const char *query, bool ignore_command_ok)
return NULL; return NULL;
} }
var = GetVariable(pset.vars, "ECHO_HIDDEN"); echo_hidden = SwitchVariable(pset.vars, "ECHO_HIDDEN", "noexec", NULL);
if (var) if (echo_hidden != var_notset)
{ {
printf("********* QUERY **********\n" printf("********* QUERY **********\n"
"%s\n" "%s\n"
"**************************\n\n", query); "**************************\n\n", query);
fflush(stdout); fflush(stdout);
}
if (var && strcmp(var, "noexec") == 0) if (echo_hidden == 1)
return NULL; return NULL;
}
/* discard any uneaten results of past queries */ /* discard any uneaten results of past queries */
while ((newres = PQgetResult(pset.db)) != NULL) while ((newres = PQgetResult(pset.db)) != NULL)
...@@ -579,13 +579,13 @@ SendQuery(const char *query) ...@@ -579,13 +579,13 @@ SendQuery(const char *query)
bool OK; bool OK;
if (!pset.db) if (!pset.db)
{ {
psql_error("You are currently not connected to a database.\n"); psql_error("You are currently not connected to a database.\n");
return false; return false;
} }
if (GetVariableBool(pset.vars, "SINGLESTEP")) if (GetVariableBool(pset.vars, "SINGLESTEP"))
{ {
char buf[3]; char buf[3];
printf(gettext("***(Single step mode: Verify query)*********************************************\n" printf(gettext("***(Single step mode: Verify query)*********************************************\n"
...@@ -596,14 +596,9 @@ SendQuery(const char *query) ...@@ -596,14 +596,9 @@ SendQuery(const char *query)
if (fgets(buf, sizeof(buf), stdin) != NULL) if (fgets(buf, sizeof(buf), stdin) != NULL)
if (buf[0] == 'x') if (buf[0] == 'x')
return false; return false;
}
else
{
const char *var = GetVariable(pset.vars, "ECHO");
if (var && strncmp(var, "queries", strlen(var)) == 0)
puts(query);
} }
else if (VariableEquals(pset.vars, "ECHO", "queries"))
puts(query);
SetCancelConn(); SetCancelConn();
...@@ -619,3 +614,15 @@ SendQuery(const char *query) ...@@ -619,3 +614,15 @@ SendQuery(const char *query)
PrintNotifications(); PrintNotifications();
return OK; return OK;
} }
char parse_char(char **buf)
{
long l;
l = strtol(*buf, buf, 0);
(*buf)--;
return (char)l;
}
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* *
* Copyright 2000 by PostgreSQL Global Development Group * Copyright 2000 by PostgreSQL Global Development Group
* *
* $Header: /cvsroot/pgsql/src/bin/psql/common.h,v 1.23 2003/03/20 06:00:12 momjian Exp $ * $Header: /cvsroot/pgsql/src/bin/psql/common.h,v 1.24 2003/03/20 06:43:35 momjian Exp $
*/ */
#ifndef COMMON_H #ifndef COMMON_H
#define COMMON_H #define COMMON_H
...@@ -42,6 +42,12 @@ extern bool SendQuery(const char *query); ...@@ -42,6 +42,12 @@ extern bool SendQuery(const char *query);
/* sprompt.h */ /* sprompt.h */
extern char *simple_prompt(const char *prompt, int maxlen, bool echo); extern char *simple_prompt(const char *prompt, int maxlen, bool echo);
/* Parse a numeric character code from the string pointed at by *buf, e.g.
* one written as 0x0c (hexadecimal) or 015 (octal); advance *buf to the last
* character of the numeric character code.
*/
extern char parse_char(char **buf);
/* Used for all Win32 popen/pclose calls */ /* Used for all Win32 popen/pclose calls */
#ifdef WIN32 #ifdef WIN32
#define popen(x,y) _popen(x,y) #define popen(x,y) _popen(x,y)
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* *
* Copyright 2000 by PostgreSQL Global Development Group * Copyright 2000 by PostgreSQL Global Development Group
* *
* $Header: /cvsroot/pgsql/src/bin/psql/input.c,v 1.22 2003/03/20 06:00:12 momjian Exp $ * $Header: /cvsroot/pgsql/src/bin/psql/input.c,v 1.23 2003/03/20 06:43:35 momjian Exp $
*/ */
#include "postgres_fe.h" #include "postgres_fe.h"
#include "input.h" #include "input.h"
...@@ -233,10 +233,12 @@ finishInput(int exitstatus, void *arg) ...@@ -233,10 +233,12 @@ finishInput(int exitstatus, void *arg)
strlen(PSQLHISTORY) + 1); strlen(PSQLHISTORY) + 1);
if (psql_history) if (psql_history)
{ {
const char *var = GetVariable(pset.vars, "HISTSIZE"); int hist_size;
hist_size = GetVariableNum(pset.vars,"HISTSIZE",-1,-1,true);
if (hist_size >= 0)
stifle_history(hist_size);
if (var)
stifle_history(atoi(var));
sprintf(psql_history, "%s/%s", home, PSQLHISTORY); sprintf(psql_history, "%s/%s", home, PSQLHISTORY);
write_history(psql_history); write_history(psql_history);
free(psql_history); free(psql_history);
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* *
* Copyright 2000-2002 by PostgreSQL Global Development Group * Copyright 2000-2002 by PostgreSQL Global Development Group
* *
* $Header: /cvsroot/pgsql/src/bin/psql/large_obj.c,v 1.23 2002/10/15 02:24:16 tgl Exp $ * $Header: /cvsroot/pgsql/src/bin/psql/large_obj.c,v 1.24 2003/03/20 06:43:35 momjian Exp $
*/ */
#include "postgres_fe.h" #include "postgres_fe.h"
#include "large_obj.h" #include "large_obj.h"
...@@ -40,15 +40,20 @@ _my_notice_handler(void *arg, const char *message) ...@@ -40,15 +40,20 @@ _my_notice_handler(void *arg, const char *message)
static bool static bool
handle_transaction(void) handle_transaction(void)
{ {
const char *var = GetVariable(pset.vars, "LO_TRANSACTION");
PGresult *res; PGresult *res;
bool commit; bool commit = false;
PQnoticeProcessor old_notice_hook; PQnoticeProcessor old_notice_hook;
if (var && strcmp(var, "nothing") == 0) switch (SwitchVariable(pset.vars, "LO_TRANSACTION",
"nothing",
"commit",
NULL))
{
case 1:
return true; return true;
case 2:
commit = (var && strcmp(var, "commit") == 0); commit = true;
}
notice[0] = '\0'; notice[0] = '\0';
old_notice_hook = PQsetNoticeProcessor(pset.db, _my_notice_handler, NULL); old_notice_hook = PQsetNoticeProcessor(pset.db, _my_notice_handler, NULL);
...@@ -87,11 +92,9 @@ do_lo_export(const char *loid_arg, const char *filename_arg) ...@@ -87,11 +92,9 @@ do_lo_export(const char *loid_arg, const char *filename_arg)
{ {
PGresult *res; PGresult *res;
int status; int status;
bool own_transaction = true; bool own_transaction;
const char *var = GetVariable(pset.vars, "LO_TRANSACTION");
if (var && strcmp(var, "nothing") == 0) own_transaction = VariableEquals(pset.vars, "LO_TRANSACTION", "nothing");
own_transaction = false;
if (!pset.db) if (!pset.db)
{ {
...@@ -154,11 +157,9 @@ do_lo_import(const char *filename_arg, const char *comment_arg) ...@@ -154,11 +157,9 @@ do_lo_import(const char *filename_arg, const char *comment_arg)
Oid loid; Oid loid;
char oidbuf[32]; char oidbuf[32];
unsigned int i; unsigned int i;
bool own_transaction = true; bool own_transaction;
const char *var = GetVariable(pset.vars, "LO_TRANSACTION");
if (var && strcmp(var, "nothing") == 0) own_transaction = VariableEquals(pset.vars, "LO_TRANSACTION", "nothing");
own_transaction = false;
if (!pset.db) if (!pset.db)
{ {
...@@ -271,11 +272,10 @@ do_lo_unlink(const char *loid_arg) ...@@ -271,11 +272,10 @@ do_lo_unlink(const char *loid_arg)
int status; int status;
Oid loid = atooid(loid_arg); Oid loid = atooid(loid_arg);
char buf[256]; char buf[256];
bool own_transaction = true;
const char *var = GetVariable(pset.vars, "LO_TRANSACTION");
if (var && strcmp(var, "nothing") == 0) bool own_transaction;
own_transaction = false;
own_transaction = VariableEquals(pset.vars, "LO_TRANSACTION", "nothing");
if (!pset.db) if (!pset.db)
{ {
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* *
* Copyright 2000 by PostgreSQL Global Development Group * Copyright 2000 by PostgreSQL Global Development Group
* *
* $Header: /cvsroot/pgsql/src/bin/psql/mainloop.c,v 1.52 2003/03/20 06:00:12 momjian Exp $ * $Header: /cvsroot/pgsql/src/bin/psql/mainloop.c,v 1.53 2003/03/20 06:43:35 momjian Exp $
*/ */
#include "postgres_fe.h" #include "postgres_fe.h"
#include "mainloop.h" #include "mainloop.h"
...@@ -40,16 +40,14 @@ MainLoop(FILE *source) ...@@ -40,16 +40,14 @@ MainLoop(FILE *source)
char *line; /* current line of input */ char *line; /* current line of input */
int len; /* length of the line */ int len; /* length of the line */
volatile int successResult = EXIT_SUCCESS; volatile int successResult = EXIT_SUCCESS;
volatile backslashResult slashCmdStatus; volatile backslashResult slashCmdStatus = CMD_UNKNOWN;
bool success; bool success;
volatile char in_quote; /* == 0 for no in_quote */ volatile char in_quote = 0; /* == 0 for no in_quote */
volatile bool in_xcomment; /* in extended comment */ volatile int in_xcomment = 0; /* in extended comment */
volatile int xcdepth; volatile int paren_level = 0;
volatile int paren_level;
unsigned int query_start; unsigned int query_start;
volatile int count_eof = 0; volatile int count_eof = 0;
const char *var;
volatile unsigned int bslash_count = 0; volatile unsigned int bslash_count = 0;
int i, int i,
...@@ -81,16 +79,12 @@ MainLoop(FILE *source) ...@@ -81,16 +79,12 @@ MainLoop(FILE *source)
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
in_xcomment = false;
in_quote = 0;
paren_level = 0;
slashCmdStatus = CMD_UNKNOWN; /* set default */
prev_lineno = pset.lineno; prev_lineno = pset.lineno;
pset.lineno = 0; pset.lineno = 0;
/* main loop to get queries and execute them */ /* main loop to get queries and execute them */
while (1) while (successResult == EXIT_SUCCESS)
{ {
/* /*
* Welcome code for Control-C * Welcome code for Control-C
...@@ -109,6 +103,7 @@ MainLoop(FILE *source) ...@@ -109,6 +103,7 @@ MainLoop(FILE *source)
} }
cancel_pressed = false; cancel_pressed = false;
fflush(stdout);
} }
#ifndef WIN32 #ifndef WIN32
...@@ -118,15 +113,16 @@ MainLoop(FILE *source) ...@@ -118,15 +113,16 @@ MainLoop(FILE *source)
if (pset.cur_cmd_interactive) if (pset.cur_cmd_interactive)
{ {
fputc('\n', stdout); putc('\n', stdout);
resetPQExpBuffer(query_buf); resetPQExpBuffer(query_buf);
/* reset parsing state */ /* reset parsing state */
in_xcomment = false; in_xcomment = 0;
in_quote = 0; in_quote = 0;
paren_level = 0; paren_level = 0;
count_eof = 0; count_eof = 0;
slashCmdStatus = CMD_UNKNOWN; slashCmdStatus = CMD_UNKNOWN;
fflush(stdout);
} }
else else
{ {
...@@ -151,23 +147,21 @@ MainLoop(FILE *source) ...@@ -151,23 +147,21 @@ MainLoop(FILE *source)
line = xstrdup(query_buf->data); line = xstrdup(query_buf->data);
resetPQExpBuffer(query_buf); resetPQExpBuffer(query_buf);
/* reset parsing state since we are rescanning whole line */ /* reset parsing state since we are rescanning whole line */
in_xcomment = false; in_xcomment = 0;
in_quote = 0; in_quote = 0;
paren_level = 0; paren_level = 0;
slashCmdStatus = CMD_UNKNOWN; slashCmdStatus = CMD_UNKNOWN;
} }
else
{
fflush(stdout);
/* /*
* otherwise, set interactive prompt if necessary and get * otherwise, set interactive prompt if necessary and get
* another line * another line
*/ */
if (pset.cur_cmd_interactive) else if (pset.cur_cmd_interactive)
{ {
int prompt_status; int prompt_status;
fflush(stdout);
if (in_quote && in_quote == '\'') if (in_quote && in_quote == '\'')
prompt_status = PROMPT_SINGLEQUOTE; prompt_status = PROMPT_SINGLEQUOTE;
else if (in_quote && in_quote == '"') else if (in_quote && in_quote == '"')
...@@ -185,7 +179,6 @@ MainLoop(FILE *source) ...@@ -185,7 +179,6 @@ MainLoop(FILE *source)
} }
else else
line = gets_fromFile(source); line = gets_fromFile(source);
}
/* Setting this will not have effect until next line. */ /* Setting this will not have effect until next line. */
...@@ -203,50 +196,21 @@ MainLoop(FILE *source) ...@@ -203,50 +196,21 @@ MainLoop(FILE *source)
{ {
if (pset.cur_cmd_interactive) if (pset.cur_cmd_interactive)
{ {
bool getout = true;
/* This tries to mimic bash's IGNOREEOF feature. */ /* This tries to mimic bash's IGNOREEOF feature. */
const char *val = GetVariable(pset.vars, "IGNOREEOF"); count_eof++;
if (val)
{
long int maxeof;
char *endptr;
if (*val == '\0')
maxeof = 10;
else
{
maxeof = strtol(val, &endptr, 0);
if (*endptr != '\0') /* string not valid as a
* number */
maxeof = 10;
}
if (count_eof++ != maxeof)
getout = false; /* not quite there yet */
}
if (getout) if (count_eof < GetVariableNum(pset.vars,"IGNOREEOF",0,10,false))
{
if (QUIET())
putc('\n', stdout);
else
puts("\\q");
break;
}
else
{ {
if (!QUIET()) if (!QUIET())
printf(gettext("Use \"\\q\" to leave %s.\n"), pset.progname); printf(gettext("Use \"\\q\" to leave %s.\n"), pset.progname);
continue; continue;
} }
puts(QUIET() ? "" : "\\q");
} }
else
/* not interactive */
break; break;
} }
else
count_eof = 0; count_eof = 0;
pset.lineno++; pset.lineno++;
...@@ -259,8 +223,7 @@ MainLoop(FILE *source) ...@@ -259,8 +223,7 @@ MainLoop(FILE *source)
} }
/* echo back if flag is set */ /* echo back if flag is set */
var = GetVariable(pset.vars, "ECHO"); if (!pset.cur_cmd_interactive && VariableEquals(pset.vars, "ECHO", "all"))
if (!pset.cur_cmd_interactive && var && strcmp(var, "all") == 0)
puts(line); puts(line);
fflush(stdout); fflush(stdout);
...@@ -276,14 +239,13 @@ MainLoop(FILE *source) ...@@ -276,14 +239,13 @@ MainLoop(FILE *source)
#define ADVANCE_1 (prevlen = thislen, i += thislen, thislen = PQmblen(line+i, pset.encoding)) #define ADVANCE_1 (prevlen = thislen, i += thislen, thislen = PQmblen(line+i, pset.encoding))
success = true; success = true;
for (i = 0, prevlen = 0, thislen = (len > 0) ? PQmblen(line, pset.encoding) : 0; prevlen = 0;
i < len; thislen = ((len > 0) ? PQmblen(line, pset.encoding) : 0);
ADVANCE_1)
for (i = 0; (i < len) && (success || !die_on_error); ADVANCE_1)
{ {
/* was the previous character a backslash? */ /* was the previous character a backslash? */
bool was_bslash = (i > 0 && line[i - prevlen] == '\\'); if (i > 0 && line[i - prevlen] == '\\')
if (was_bslash)
bslash_count++; bslash_count++;
else else
bslash_count = 0; bslash_count = 0;
...@@ -308,30 +270,24 @@ MainLoop(FILE *source) ...@@ -308,30 +270,24 @@ MainLoop(FILE *source)
in_quote = 0; in_quote = 0;
} }
/* in extended comment? */ /* start of extended comment? */
else if (in_xcomment) else if (line[i] == '/' && line[i + thislen] == '*')
{
if (line[i] == '*' && line[i + thislen] == '/')
{
if (xcdepth > 0)
xcdepth--;
else
{ {
in_xcomment = false; in_xcomment++;
if (in_xcomment == 1)
ADVANCE_1; ADVANCE_1;
} }
}
else if (line[i] == '/' && line[i + thislen] == '*')
xcdepth++;
}
/* start of extended comment? */ /* end of extended comment? */
else if (line[i] == '/' && line[i + thislen] == '*') else if (line[i] == '*' && line[i + thislen] == '/')
{ {
xcdepth = 0; in_xcomment--;
in_xcomment = true; if (in_xcomment <= 0)
{
in_xcomment = 0;
ADVANCE_1; ADVANCE_1;
} }
}
/* start of quote? */ /* start of quote? */
else if (line[i] == '\'' || line[i] == '"') else if (line[i] == '\'' || line[i] == '"')
...@@ -353,7 +309,7 @@ MainLoop(FILE *source) ...@@ -353,7 +309,7 @@ MainLoop(FILE *source)
/* colon -> substitute variable */ /* colon -> substitute variable */
/* we need to be on the watch for the '::' operator */ /* we need to be on the watch for the '::' operator */
else if (line[i] == ':' && !was_bslash else if (line[i] == ':' && !bslash_count
&& strspn(line + i + thislen, VALID_VARIABLE_CHARS) > 0 && strspn(line + i + thislen, VALID_VARIABLE_CHARS) > 0
&& !(prevlen > 0 && line[i - prevlen] == ':') && !(prevlen > 0 && line[i - prevlen] == ':')
) )
...@@ -411,7 +367,7 @@ MainLoop(FILE *source) ...@@ -411,7 +367,7 @@ MainLoop(FILE *source)
} }
/* semicolon? then send query */ /* semicolon? then send query */
else if (line[i] == ';' && !was_bslash && !paren_level) else if (line[i] == ';' && !bslash_count && !paren_level)
{ {
line[i] = '\0'; line[i] = '\0';
/* is there anything else on the line? */ /* is there anything else on the line? */
...@@ -442,7 +398,7 @@ MainLoop(FILE *source) ...@@ -442,7 +398,7 @@ MainLoop(FILE *source)
* if you have a burning need to send a semicolon or colon to * if you have a burning need to send a semicolon or colon to
* the backend ... * the backend ...
*/ */
else if (was_bslash && (line[i] == ';' || line[i] == ':')) else if (bslash_count && (line[i] == ';' || line[i] == ':'))
{ {
/* remove the backslash */ /* remove the backslash */
memmove(line + i - prevlen, line + i, len - i + 1); memmove(line + i - prevlen, line + i, len - i + 1);
...@@ -451,7 +407,7 @@ MainLoop(FILE *source) ...@@ -451,7 +407,7 @@ MainLoop(FILE *source)
} }
/* backslash command */ /* backslash command */
else if (was_bslash) else if (bslash_count)
{ {
const char *end_of_cmd = NULL; const char *end_of_cmd = NULL;
...@@ -499,15 +455,9 @@ MainLoop(FILE *source) ...@@ -499,15 +455,9 @@ MainLoop(FILE *source)
paren_level = 0; paren_level = 0;
/* process anything left after the backslash command */ /* process anything left after the backslash command */
i += end_of_cmd - &line[i]; i = end_of_cmd - line;
query_start = i; query_start = i;
} }
/* stop the script after error */
if (!success && die_on_error)
break;
} /* for (line) */ } /* for (line) */
...@@ -533,25 +483,19 @@ MainLoop(FILE *source) ...@@ -533,25 +483,19 @@ MainLoop(FILE *source)
if (query_buf->data[0] != '\0' && GetVariableBool(pset.vars, "SINGLELINE")) if (query_buf->data[0] != '\0' && GetVariableBool(pset.vars, "SINGLELINE"))
{ {
success = SendQuery(query_buf->data); success = SendQuery(query_buf->data);
slashCmdStatus = success ? CMD_SEND : CMD_ERROR; slashCmdStatus = (success ? CMD_SEND : CMD_ERROR);
resetPQExpBuffer(previous_buf); resetPQExpBuffer(previous_buf);
appendPQExpBufferStr(previous_buf, query_buf->data); appendPQExpBufferStr(previous_buf, query_buf->data);
resetPQExpBuffer(query_buf); resetPQExpBuffer(query_buf);
} }
if (!pset.cur_cmd_interactive)
if (!success && die_on_error && !pset.cur_cmd_interactive)
{ {
if (!success && die_on_error)
successResult = EXIT_USER; successResult = EXIT_USER;
break;
}
/* Have we lost the db connection? */ /* Have we lost the db connection? */
if (pset.db == NULL && !pset.cur_cmd_interactive) else if (!pset.db)
{
successResult = EXIT_BADCONN; successResult = EXIT_BADCONN;
break;
} }
} /* while !endoffile/session */ } /* while !endoffile/session */
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* *
* Copyright 2000 by PostgreSQL Global Development Group * Copyright 2000 by PostgreSQL Global Development Group
* *
* $Header: /cvsroot/pgsql/src/bin/psql/prompt.c,v 1.22 2001/10/25 05:49:54 momjian Exp $ * $Header: /cvsroot/pgsql/src/bin/psql/prompt.c,v 1.23 2003/03/20 06:43:35 momjian Exp $
*/ */
#include "postgres_fe.h" #include "postgres_fe.h"
#include "prompt.h" #include "prompt.h"
...@@ -69,17 +69,30 @@ get_prompt(promptStatus_t status) ...@@ -69,17 +69,30 @@ get_prompt(promptStatus_t status)
char buf[MAX_PROMPT_SIZE + 1]; char buf[MAX_PROMPT_SIZE + 1];
bool esc = false; bool esc = false;
const char *p; const char *p;
const char *prompt_string; const char *prompt_string = "? ";
const char *prompt_name = NULL;
if (status == PROMPT_READY) switch (status)
prompt_string = GetVariable(pset.vars, "PROMPT1"); {
else if (status == PROMPT_CONTINUE || status == PROMPT_SINGLEQUOTE || status == PROMPT_DOUBLEQUOTE || status == PROMPT_COMMENT || status == PROMPT_PAREN) case PROMPT_READY:
prompt_string = GetVariable(pset.vars, "PROMPT2"); prompt_name = "PROMPT1";
else if (status == PROMPT_COPY) break;
prompt_string = GetVariable(pset.vars, "PROMPT3");
else case PROMPT_CONTINUE:
prompt_string = "? "; case PROMPT_SINGLEQUOTE:
case PROMPT_DOUBLEQUOTE:
case PROMPT_COMMENT:
case PROMPT_PAREN:
prompt_name = "PROMPT2";
break;
case PROMPT_COPY:
prompt_name = "PROMPT3";
break;
}
if (prompt_name)
prompt_string = GetVariable(pset.vars, prompt_name);
destination[0] = '\0'; destination[0] = '\0';
...@@ -92,21 +105,15 @@ get_prompt(promptStatus_t status) ...@@ -92,21 +105,15 @@ get_prompt(promptStatus_t status)
{ {
switch (*p) switch (*p)
{ {
case '%':
strcpy(buf, "%");
break;
/* Current database */ /* Current database */
case '/': case '/':
if (pset.db) if (pset.db)
strncpy(buf, PQdb(pset.db), MAX_PROMPT_SIZE); strncpy(buf, PQdb(pset.db), MAX_PROMPT_SIZE);
break; break;
case '~': case '~':
{
const char *var;
if (pset.db) if (pset.db)
{ {
const char *var;
if (strcmp(PQdb(pset.db), PQuser(pset.db)) == 0 || if (strcmp(PQdb(pset.db), PQuser(pset.db)) == 0 ||
((var = getenv("PGDATABASE")) && strcmp(var, PQdb(pset.db)) == 0)) ((var = getenv("PGDATABASE")) && strcmp(var, PQdb(pset.db)) == 0))
strcpy(buf, "~"); strcpy(buf, "~");
...@@ -114,7 +121,7 @@ get_prompt(promptStatus_t status) ...@@ -114,7 +121,7 @@ get_prompt(promptStatus_t status)
strncpy(buf, PQdb(pset.db), MAX_PROMPT_SIZE); strncpy(buf, PQdb(pset.db), MAX_PROMPT_SIZE);
} }
break; break;
}
/* DB server hostname (long/short) */ /* DB server hostname (long/short) */
case 'M': case 'M':
case 'm': case 'm':
...@@ -164,15 +171,8 @@ get_prompt(promptStatus_t status) ...@@ -164,15 +171,8 @@ get_prompt(promptStatus_t status)
case '7': case '7':
case '8': case '8':
case '9': case '9':
{ *buf = parse_char(&p);
long int l;
char *end;
l = strtol(p, &end, 0);
sprintf(buf, "%c", (unsigned char) l);
p = end - 1;
break; break;
}
case 'R': case 'R':
switch (status) switch (status)
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* *
* Copyright 2000 by PostgreSQL Global Development Group * Copyright 2000 by PostgreSQL Global Development Group
* *
* $Header: /cvsroot/pgsql/src/bin/psql/startup.c,v 1.71 2003/03/18 22:15:44 petere Exp $ * $Header: /cvsroot/pgsql/src/bin/psql/startup.c,v 1.72 2003/03/20 06:43:35 momjian Exp $
*/ */
#include "postgres_fe.h" #include "postgres_fe.h"
...@@ -253,10 +253,9 @@ main(int argc, char *argv[]) ...@@ -253,10 +253,9 @@ main(int argc, char *argv[])
*/ */
else if (options.action == ACT_SINGLE_SLASH) else if (options.action == ACT_SINGLE_SLASH)
{ {
const char *value; if (VariableEquals(pset.vars, "ECHO", "all"))
if ((value = GetVariable(pset.vars, "ECHO")) && strcmp(value, "all") == 0)
puts(options.action_string); puts(options.action_string);
successResult = HandleSlashCmds(options.action_string, NULL, NULL, NULL) != CMD_ERROR successResult = HandleSlashCmds(options.action_string, NULL, NULL, NULL) != CMD_ERROR
? EXIT_SUCCESS : EXIT_FAILURE; ? EXIT_SUCCESS : EXIT_FAILURE;
} }
...@@ -266,10 +265,9 @@ main(int argc, char *argv[]) ...@@ -266,10 +265,9 @@ main(int argc, char *argv[])
*/ */
else if (options.action == ACT_SINGLE_QUERY) else if (options.action == ACT_SINGLE_QUERY)
{ {
const char *value; if (VariableEquals(pset.vars, "ECHO", "all"))
if ((value = GetVariable(pset.vars, "ECHO")) && strcmp(value, "all") == 0)
puts(options.action_string); puts(options.action_string);
successResult = SendQuery(options.action_string) successResult = SendQuery(options.action_string)
? EXIT_SUCCESS : EXIT_FAILURE; ? EXIT_SUCCESS : EXIT_FAILURE;
} }
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* *
* Copyright 2000 by PostgreSQL Global Development Group * Copyright 2000 by PostgreSQL Global Development Group
* *
* $Header: /cvsroot/pgsql/src/bin/psql/variables.c,v 1.9 2001/02/10 02:31:28 tgl Exp $ * $Header: /cvsroot/pgsql/src/bin/psql/variables.c,v 1.10 2003/03/20 06:43:35 momjian Exp $
*/ */
#include "postgres_fe.h" #include "postgres_fe.h"
#include "variables.h" #include "variables.h"
...@@ -68,6 +68,74 @@ GetVariableBool(VariableSpace space, const char *name) ...@@ -68,6 +68,74 @@ GetVariableBool(VariableSpace space, const char *name)
} }
bool
VariableEquals(VariableSpace space, const char name[], const char value[])
{
const char *var;
var = GetVariable(space, name);
return var && (strcmp(var, value) == 0);
}
int
GetVariableNum(VariableSpace space,
const char name[],
int defaultval,
int faultval,
bool allowtrail)
{
const char *var;
int result;
var = GetVariable(space, name);
if (!var)
result = defaultval;
else if (!var[0])
result = faultval;
else
{
char *end;
result = strtol(var, &end, 0);
if (!allowtrail && *end)
result = faultval;
}
return result;
}
int
SwitchVariable(VariableSpace space, const char name[], const char *opt, ...)
{
int result;
const char *var;
var = GetVariable(space, name);
if (var)
{
va_list args;
va_start(args, opt);
for (result=1; opt && (strcmp(var, opt) != 0); result++)
opt = va_arg(args,const char *);
if (!opt) result = var_notfound;
va_end(args);
}
else
result = var_notset;
return result;
}
void
PrintVariables(VariableSpace space)
{
struct _variable *ptr;
for (ptr = space->next; ptr; ptr = ptr->next)
printf("%s = '%s'\n", ptr->name, ptr->value);
}
bool bool
SetVariable(VariableSpace space, const char *name, const char *value) SetVariable(VariableSpace space, const char *name, const char *value)
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* *
* Copyright 2000 by PostgreSQL Global Development Group * Copyright 2000 by PostgreSQL Global Development Group
* *
* $Header: /cvsroot/pgsql/src/bin/psql/variables.h,v 1.10 2001/11/05 17:46:31 momjian Exp $ * $Header: /cvsroot/pgsql/src/bin/psql/variables.h,v 1.11 2003/03/20 06:43:35 momjian Exp $
*/ */
/* /*
...@@ -30,10 +30,33 @@ typedef struct _variable *VariableSpace; ...@@ -30,10 +30,33 @@ typedef struct _variable *VariableSpace;
VariableSpace CreateVariableSpace(void); VariableSpace CreateVariableSpace(void);
const char *GetVariable(VariableSpace space, const char *name); const char *GetVariable(VariableSpace space, const char *name);
bool GetVariableBool(VariableSpace space, const char *name); bool GetVariableBool(VariableSpace space, const char *name);
bool SetVariable(VariableSpace space, const char *name, const char *value); bool VariableEquals(VariableSpace space, const char name[], const char *opt);
bool SetVariableBool(VariableSpace space, const char *name);
bool DeleteVariable(VariableSpace space, const char *name); /* Read numeric variable, or defaultval if it is not set, or faultval if its
void DestroyVariableSpace(VariableSpace space); * value is not a valid numeric string. If allowtrail is false, this will
* include the case where there are trailing characters after the number.
*/
int GetVariableNum(VariableSpace space,
const char name[],
int defaultval,
int faultval,
bool allowtrail);
/* Find value of variable <name> among NULL-terminated list of alternative
* options. Returns var_notset if the variable was not set, var_notfound if its
* value did not occur in the list of options, or the number of the matching
* option. The first option is 1, the second is 2 and so on.
*/
enum { var_notset = 0, var_notfound = -1 };
int SwitchVariable(VariableSpace space, const char name[], const char *opt,...);
void PrintVariables(VariableSpace space);
bool SetVariable(VariableSpace space, const char *name, const char *value);
bool SetVariableBool(VariableSpace space, const char *name);
bool DeleteVariable(VariableSpace space, const char *name);
void DestroyVariableSpace(VariableSpace space);
#endif /* VARIABLES_H */ #endif /* VARIABLES_H */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment