*
* 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 "command.h"
if (!opt0)
{
/* list all variables */
-
- /*
- * 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);
+ PrintVariables(pset.vars);
success = true;
}
else
save_char = options_string[pos + token_end + 1];
options_string[pos + token_end + 1] = '\0';
value = GetVariable(pset.vars, options_string + pos + 1);
- if (!value)
- value = "";
- return_val = xstrdup(value);
+ return_val = xstrdup(value ? value : "");
options_string[pos + token_end + 1] = save_char;
*string = &options_string[pos + token_end + 1];
/* XXX should we set *quote to ':' here? */
case '7':
case '8':
case '9':
- {
- long int l;
- char *end;
-
- l = strtol(p, &end, 0);
- c = (char) l;
- p = end - 1;
+ c = parse_char((char **)&p);
break;
- }
+
default:
c = *p;
}
*
* 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 "common.h"
{
PGresult *res = NULL;
PGresult *newres;
- const char *var;
+ int echo_hidden;
ExecStatusType rstatus;
if (!pset.db)
return NULL;
}
- var = GetVariable(pset.vars, "ECHO_HIDDEN");
- if (var)
+ echo_hidden = SwitchVariable(pset.vars, "ECHO_HIDDEN", "noexec", NULL);
+ if (echo_hidden != var_notset)
{
printf("********* QUERY **********\n"
"%s\n"
"**************************\n\n", query);
fflush(stdout);
- }
- if (var && strcmp(var, "noexec") == 0)
+ if (echo_hidden == 1)
return NULL;
+ }
/* discard any uneaten results of past queries */
while ((newres = PQgetResult(pset.db)) != NULL)
bool OK;
if (!pset.db)
- {
+ {
psql_error("You are currently not connected to a database.\n");
return false;
- }
+ }
if (GetVariableBool(pset.vars, "SINGLESTEP"))
- {
+ {
char buf[3];
printf(gettext("***(Single step mode: Verify query)*********************************************\n"
if (fgets(buf, sizeof(buf), stdin) != NULL)
if (buf[0] == 'x')
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();
PrintNotifications();
return OK;
}
+
+
+char parse_char(char **buf)
+{
+ long l;
+
+ l = strtol(*buf, buf, 0);
+ (*buf)--;
+ return (char)l;
+}
+
+
*
* 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
#define COMMON_H
/* sprompt.h */
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 */
#ifdef WIN32
#define popen(x,y) _popen(x,y)
*
* 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 "input.h"
strlen(PSQLHISTORY) + 1);
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);
write_history(psql_history);
free(psql_history);
*
* 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 "large_obj.h"
static bool
handle_transaction(void)
{
- const char *var = GetVariable(pset.vars, "LO_TRANSACTION");
PGresult *res;
- bool commit;
+ bool commit = false;
PQnoticeProcessor old_notice_hook;
- if (var && strcmp(var, "nothing") == 0)
+ switch (SwitchVariable(pset.vars, "LO_TRANSACTION",
+ "nothing",
+ "commit",
+ NULL))
+ {
+ case 1:
return true;
-
- commit = (var && strcmp(var, "commit") == 0);
+ case 2:
+ commit = true;
+ }
notice[0] = '\0';
old_notice_hook = PQsetNoticeProcessor(pset.db, _my_notice_handler, NULL);
{
PGresult *res;
int status;
- bool own_transaction = true;
- const char *var = GetVariable(pset.vars, "LO_TRANSACTION");
+ bool own_transaction;
- if (var && strcmp(var, "nothing") == 0)
- own_transaction = false;
+ own_transaction = VariableEquals(pset.vars, "LO_TRANSACTION", "nothing");
if (!pset.db)
{
Oid loid;
char oidbuf[32];
unsigned int i;
- bool own_transaction = true;
- const char *var = GetVariable(pset.vars, "LO_TRANSACTION");
+ bool own_transaction;
- if (var && strcmp(var, "nothing") == 0)
- own_transaction = false;
+ own_transaction = VariableEquals(pset.vars, "LO_TRANSACTION", "nothing");
if (!pset.db)
{
int status;
Oid loid = atooid(loid_arg);
char buf[256];
- bool own_transaction = true;
- const char *var = GetVariable(pset.vars, "LO_TRANSACTION");
- if (var && strcmp(var, "nothing") == 0)
- own_transaction = false;
+ bool own_transaction;
+
+ own_transaction = VariableEquals(pset.vars, "LO_TRANSACTION", "nothing");
if (!pset.db)
{
*
* 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 "mainloop.h"
char *line; /* current line of input */
int len; /* length of the line */
volatile int successResult = EXIT_SUCCESS;
- volatile backslashResult slashCmdStatus;
+ volatile backslashResult slashCmdStatus = CMD_UNKNOWN;
bool success;
- volatile char in_quote; /* == 0 for no in_quote */
- volatile bool in_xcomment; /* in extended comment */
- volatile int xcdepth;
- volatile int paren_level;
+ volatile char in_quote = 0; /* == 0 for no in_quote */
+ volatile int in_xcomment = 0; /* in extended comment */
+ volatile int paren_level = 0;
unsigned int query_start;
volatile int count_eof = 0;
- const char *var;
volatile unsigned int bslash_count = 0;
int i,
exit(EXIT_FAILURE);
}
- in_xcomment = false;
- in_quote = 0;
- paren_level = 0;
- slashCmdStatus = CMD_UNKNOWN; /* set default */
prev_lineno = pset.lineno;
pset.lineno = 0;
/* main loop to get queries and execute them */
- while (1)
+ while (successResult == EXIT_SUCCESS)
{
/*
* Welcome code for Control-C
}
cancel_pressed = false;
+ fflush(stdout);
}
#ifndef WIN32
if (pset.cur_cmd_interactive)
{
- fputc('\n', stdout);
+ putc('\n', stdout);
resetPQExpBuffer(query_buf);
/* reset parsing state */
- in_xcomment = false;
+ in_xcomment = 0;
in_quote = 0;
paren_level = 0;
count_eof = 0;
slashCmdStatus = CMD_UNKNOWN;
+ fflush(stdout);
}
else
{
line = xstrdup(query_buf->data);
resetPQExpBuffer(query_buf);
/* reset parsing state since we are rescanning whole line */
- in_xcomment = false;
+ in_xcomment = 0;
in_quote = 0;
paren_level = 0;
slashCmdStatus = CMD_UNKNOWN;
}
- else
- {
- fflush(stdout);
-
/*
* otherwise, set interactive prompt if necessary and get
* another line
*/
- if (pset.cur_cmd_interactive)
+ else if (pset.cur_cmd_interactive)
{
int prompt_status;
+ fflush(stdout);
+
if (in_quote && in_quote == '\'')
prompt_status = PROMPT_SINGLEQUOTE;
else if (in_quote && in_quote == '"')
}
else
line = gets_fromFile(source);
- }
/* Setting this will not have effect until next line. */
{
if (pset.cur_cmd_interactive)
{
- bool getout = true;
-
/* This tries to mimic bash's IGNOREEOF feature. */
- const char *val = GetVariable(pset.vars, "IGNOREEOF");
-
- 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 */
- }
+ count_eof++;
- if (getout)
- {
- if (QUIET())
- putc('\n', stdout);
- else
- puts("\\q");
- break;
- }
- else
+ if (count_eof < GetVariableNum(pset.vars,"IGNOREEOF",0,10,false))
{
if (!QUIET())
printf(gettext("Use \"\\q\" to leave %s.\n"), pset.progname);
continue;
}
+
+ puts(QUIET() ? "" : "\\q");
}
- else
-/* not interactive */
break;
}
- else
+
count_eof = 0;
pset.lineno++;
}
/* echo back if flag is set */
- var = GetVariable(pset.vars, "ECHO");
- if (!pset.cur_cmd_interactive && var && strcmp(var, "all") == 0)
+ if (!pset.cur_cmd_interactive && VariableEquals(pset.vars, "ECHO", "all"))
puts(line);
fflush(stdout);
#define ADVANCE_1 (prevlen = thislen, i += thislen, thislen = PQmblen(line+i, pset.encoding))
success = true;
- for (i = 0, prevlen = 0, thislen = (len > 0) ? PQmblen(line, pset.encoding) : 0;
- i < len;
- ADVANCE_1)
+ prevlen = 0;
+ thislen = ((len > 0) ? PQmblen(line, pset.encoding) : 0);
+
+ for (i = 0; (i < len) && (success || !die_on_error); ADVANCE_1)
{
/* was the previous character a backslash? */
- bool was_bslash = (i > 0 && line[i - prevlen] == '\\');
-
- if (was_bslash)
+ if (i > 0 && line[i - prevlen] == '\\')
bslash_count++;
else
bslash_count = 0;
in_quote = 0;
}
- /* in extended comment? */
- else if (in_xcomment)
- {
- if (line[i] == '*' && line[i + thislen] == '/')
- {
- if (xcdepth > 0)
- xcdepth--;
- else
+ /* start of extended comment? */
+ else if (line[i] == '/' && line[i + thislen] == '*')
{
- in_xcomment = false;
+ in_xcomment++;
+ if (in_xcomment == 1)
ADVANCE_1;
}
- }
- else if (line[i] == '/' && line[i + thislen] == '*')
- xcdepth++;
- }
- /* start of extended comment? */
- else if (line[i] == '/' && line[i + thislen] == '*')
+ /* end of extended comment? */
+ else if (line[i] == '*' && line[i + thislen] == '/')
{
- xcdepth = 0;
- in_xcomment = true;
+ in_xcomment--;
+ if (in_xcomment <= 0)
+ {
+ in_xcomment = 0;
ADVANCE_1;
}
+ }
/* start of quote? */
else if (line[i] == '\'' || line[i] == '"')
/* colon -> substitute variable */
/* 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
&& !(prevlen > 0 && line[i - prevlen] == ':')
)
}
/* semicolon? then send query */
- else if (line[i] == ';' && !was_bslash && !paren_level)
+ else if (line[i] == ';' && !bslash_count && !paren_level)
{
line[i] = '\0';
/* is there anything else on the line? */
* if you have a burning need to send a semicolon or colon to
* the backend ...
*/
- else if (was_bslash && (line[i] == ';' || line[i] == ':'))
+ else if (bslash_count && (line[i] == ';' || line[i] == ':'))
{
/* remove the backslash */
memmove(line + i - prevlen, line + i, len - i + 1);
}
/* backslash command */
- else if (was_bslash)
+ else if (bslash_count)
{
const char *end_of_cmd = NULL;
paren_level = 0;
/* process anything left after the backslash command */
- i += end_of_cmd - &line[i];
+ i = end_of_cmd - line;
query_start = i;
}
-
-
- /* stop the script after error */
- if (!success && die_on_error)
- break;
-
} /* for (line) */
if (query_buf->data[0] != '\0' && GetVariableBool(pset.vars, "SINGLELINE"))
{
success = SendQuery(query_buf->data);
- slashCmdStatus = success ? CMD_SEND : CMD_ERROR;
+ slashCmdStatus = (success ? CMD_SEND : CMD_ERROR);
resetPQExpBuffer(previous_buf);
appendPQExpBufferStr(previous_buf, query_buf->data);
resetPQExpBuffer(query_buf);
}
-
- if (!success && die_on_error && !pset.cur_cmd_interactive)
+ if (!pset.cur_cmd_interactive)
{
+ if (!success && die_on_error)
successResult = EXIT_USER;
- break;
- }
-
-
/* Have we lost the db connection? */
- if (pset.db == NULL && !pset.cur_cmd_interactive)
- {
+ else if (!pset.db)
successResult = EXIT_BADCONN;
- break;
}
} /* while !endoffile/session */
*
* 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 "prompt.h"
char buf[MAX_PROMPT_SIZE + 1];
bool esc = false;
const char *p;
- const char *prompt_string;
+ const char *prompt_string = "? ";
+ const char *prompt_name = NULL;
- if (status == PROMPT_READY)
- prompt_string = GetVariable(pset.vars, "PROMPT1");
- else if (status == PROMPT_CONTINUE || status == PROMPT_SINGLEQUOTE || status == PROMPT_DOUBLEQUOTE || status == PROMPT_COMMENT || status == PROMPT_PAREN)
- prompt_string = GetVariable(pset.vars, "PROMPT2");
- else if (status == PROMPT_COPY)
- prompt_string = GetVariable(pset.vars, "PROMPT3");
- else
- prompt_string = "? ";
+ switch (status)
+ {
+ case PROMPT_READY:
+ prompt_name = "PROMPT1";
+ break;
+
+ case PROMPT_CONTINUE:
+ 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';
{
switch (*p)
{
- case '%':
- strcpy(buf, "%");
- break;
-
/* Current database */
case '/':
if (pset.db)
strncpy(buf, PQdb(pset.db), MAX_PROMPT_SIZE);
break;
case '~':
- {
- const char *var;
-
if (pset.db)
{
+ const char *var;
if (strcmp(PQdb(pset.db), PQuser(pset.db)) == 0 ||
((var = getenv("PGDATABASE")) && strcmp(var, PQdb(pset.db)) == 0))
strcpy(buf, "~");
strncpy(buf, PQdb(pset.db), MAX_PROMPT_SIZE);
}
break;
- }
+
/* DB server hostname (long/short) */
case 'M':
case 'm':
case '7':
case '8':
case '9':
- {
- long int l;
- char *end;
-
- l = strtol(p, &end, 0);
- sprintf(buf, "%c", (unsigned char) l);
- p = end - 1;
+ *buf = parse_char(&p);
break;
- }
case 'R':
switch (status)
*
* 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"
*/
else if (options.action == ACT_SINGLE_SLASH)
{
- const char *value;
-
- if ((value = GetVariable(pset.vars, "ECHO")) && strcmp(value, "all") == 0)
+ if (VariableEquals(pset.vars, "ECHO", "all"))
puts(options.action_string);
+
successResult = HandleSlashCmds(options.action_string, NULL, NULL, NULL) != CMD_ERROR
? EXIT_SUCCESS : EXIT_FAILURE;
}
*/
else if (options.action == ACT_SINGLE_QUERY)
{
- const char *value;
-
- if ((value = GetVariable(pset.vars, "ECHO")) && strcmp(value, "all") == 0)
+ if (VariableEquals(pset.vars, "ECHO", "all"))
puts(options.action_string);
+
successResult = SendQuery(options.action_string)
? EXIT_SUCCESS : EXIT_FAILURE;
}
*
* 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 "variables.h"
}
+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
SetVariable(VariableSpace space, const char *name, const char *value)
*
* 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 $
*/
/*
VariableSpace CreateVariableSpace(void);
const char *GetVariable(VariableSpace space, const char *name);
-bool GetVariableBool(VariableSpace space, const char *name);
-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);
+bool GetVariableBool(VariableSpace space, const char *name);
+bool VariableEquals(VariableSpace space, const char name[], const char *opt);
+
+/* Read numeric variable, or defaultval if it is not set, or faultval if its
+ * 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 */