1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-11 10:01:57 +03:00

Fixed psql variables vs array syntax, as well as minor psql enhancements

This commit is contained in:
Peter Eisentraut
2000-01-14 22:18:03 +00:00
parent 4ceb2d0cb6
commit 7c9390caa1
21 changed files with 1009 additions and 922 deletions

View File

@ -1,4 +1,3 @@
#include <config.h>
#include <c.h>
#include "command.h"
@ -26,6 +25,7 @@
#include "print.h"
#include "describe.h"
#include "input.h"
#include "variables.h"
#ifdef WIN32
#define popen(x,y) _popen(x,y)
@ -38,16 +38,14 @@
static backslashResult exec_command(const char *cmd,
char *const * options,
const char *options_string,
PQExpBuffer query_buf,
PsqlSettings *pset);
PQExpBuffer query_buf);
static bool do_edit(const char *filename_arg, PQExpBuffer query_buf);
static char * unescape(const char *source, PsqlSettings *pset);
static char * unescape(const char *source);
static bool do_connect(const char *new_dbname,
const char *new_user,
PsqlSettings *pset);
const char *new_user);
static bool do_shell(const char *command);
@ -79,8 +77,7 @@ static bool do_shell(const char *command);
*/
backslashResult
HandleSlashCmds(PsqlSettings *pset,
const char *line,
HandleSlashCmds(const char *line,
PQExpBuffer query_buf,
const char **end_of_cmd)
{
@ -95,6 +92,12 @@ HandleSlashCmds(PsqlSettings *pset,
const char *continue_parse = NULL; /* tell the mainloop where the
* backslash command ended */
#ifdef USE_ASSERT_CHECKING
assert(line);
assert(query_buf);
assert(end_of_cmd);
#endif
my_line = xstrdup(line);
/*
@ -135,7 +138,7 @@ HandleSlashCmds(PsqlSettings *pset,
switch (quote)
{
case '"':
options[i] = unescape(token, pset);
options[i] = unescape(token);
break;
case '\'':
options[i] = xstrdup(token);
@ -144,7 +147,7 @@ HandleSlashCmds(PsqlSettings *pset,
{
bool error = false;
FILE *fd = NULL;
char *file = unescape(token, pset);
char *file = unescape(token);
PQExpBufferData output;
char buf[512];
size_t result;
@ -200,8 +203,13 @@ HandleSlashCmds(PsqlSettings *pset,
default:
if (token[0] == '\\')
continue_parse = options_string + pos;
else if (token[0] == '$')
options[i] = xstrdup(interpolate_var(token + 1, pset));
else if (token[0] == '$')
{
const char * value = GetVariable(pset.vars, token+1);
if (!value)
value = "";
options[i] = xstrdup(value);
}
else
options[i] = xstrdup(token);
}
@ -216,7 +224,7 @@ HandleSlashCmds(PsqlSettings *pset,
}
cmd = my_line;
status = exec_command(cmd, options, options_string, query_buf, pset);
status = exec_command(cmd, options, options_string, query_buf);
if (status == CMD_UNKNOWN)
{
@ -238,15 +246,15 @@ HandleSlashCmds(PsqlSettings *pset,
new_cmd[0] = cmd[0];
new_cmd[1] = '\0';
status = exec_command(new_cmd, (char *const *) new_options, my_line + 2, query_buf, pset);
status = exec_command(new_cmd, (char *const *) new_options, my_line + 2, query_buf);
}
if (status == CMD_UNKNOWN)
{
if (pset->cur_cmd_interactive)
if (pset.cur_cmd_interactive)
fprintf(stderr, "Invalid command \\%s. Try \\? for help.\n", cmd);
else
fprintf(stderr, "%s: invalid command \\%s", pset->progname, cmd);
fprintf(stderr, "%s: invalid command \\%s", pset.progname, cmd);
status = CMD_ERROR;
}
@ -254,13 +262,10 @@ HandleSlashCmds(PsqlSettings *pset,
continue_parse += 2;
if (end_of_cmd)
{
if (continue_parse)
*end_of_cmd = line + (continue_parse - my_line);
else
*end_of_cmd = NULL;
}
if (continue_parse)
*end_of_cmd = line + (continue_parse - my_line);
else
*end_of_cmd = line + strlen(line);
/* clean up */
for (i = 0; i < NR_OPTIONS && options[i]; i++)
@ -278,12 +283,11 @@ static backslashResult
exec_command(const char *cmd,
char *const * options,
const char *options_string,
PQExpBuffer query_buf,
PsqlSettings *pset)
PQExpBuffer query_buf)
{
bool success = true; /* indicate here if the command ran ok or
* failed */
bool quiet = GetVariableBool(pset->vars, "quiet");
bool quiet = QUIET();
backslashResult status = CMD_SKIP_LINE;
@ -291,16 +295,16 @@ exec_command(const char *cmd,
/* \a -- toggle field alignment This makes little sense but we keep it around. */
if (strcmp(cmd, "a") == 0)
{
if (pset->popt.topt.format != PRINT_ALIGNED)
success = do_pset("format", "aligned", &pset->popt, quiet);
if (pset.popt.topt.format != PRINT_ALIGNED)
success = do_pset("format", "aligned", &pset.popt, quiet);
else
success = do_pset("format", "unaligned", &pset->popt, quiet);
success = do_pset("format", "unaligned", &pset.popt, quiet);
}
/* \C -- override table title (formerly change HTML caption) */
else if (strcmp(cmd, "C") == 0)
success = do_pset("title", options[0], &pset->popt, quiet);
success = do_pset("title", options[0], &pset.popt, quiet);
/*----------
@ -316,25 +320,25 @@ exec_command(const char *cmd,
{
if (options[1])
/* gave username */
success = do_connect(options[0], options[1], pset);
success = do_connect(options[0], options[1]);
else
{
if (options[0])
/* gave database name */
success = do_connect(options[0], "", pset); /* empty string is same
* username as before,
* NULL would mean libpq
* default */
success = do_connect(options[0], ""); /* empty string is same
* username as before,
* NULL would mean libpq
* default */
else
/* connect to default db as default user */
success = do_connect(NULL, NULL, pset);
success = do_connect(NULL, NULL);
}
}
/* \copy */
else if (strcmp(cmd, "copy") == 0)
success = do_copy(options_string, pset);
else if (strcasecmp(cmd, "copy") == 0)
success = do_copy(options_string);
/* \copyright */
else if (strcmp(cmd, "copyright") == 0)
@ -350,31 +354,31 @@ exec_command(const char *cmd,
case '\0':
case '?':
if (options[0])
success = describeTableDetails(options[0], pset, show_verbose);
success = describeTableDetails(options[0], show_verbose);
else
/* standard listing of interesting things */
success = listTables("tvs", NULL, pset, show_verbose);
success = listTables("tvs", NULL, show_verbose);
break;
case 'a':
success = describeAggregates(options[0], pset);
success = describeAggregates(options[0]);
break;
case 'd':
success = objectDescription(options[0], pset);
success = objectDescription(options[0]);
break;
case 'f':
success = describeFunctions(options[0], pset, show_verbose);
success = describeFunctions(options[0], show_verbose);
break;
case 'l':
success = do_lo_list(pset);
success = do_lo_list();
break;
case 'o':
success = describeOperators(options[0], pset);
success = describeOperators(options[0]);
break;
case 'p':
success = permissionsList(options[0], pset);
success = permissionsList(options[0]);
break;
case 'T':
success = describeTypes(options[0], pset, show_verbose);
success = describeTypes(options[0], show_verbose);
break;
case 't':
case 'v':
@ -382,9 +386,9 @@ exec_command(const char *cmd,
case 's':
case 'S':
if (cmd[1] == 'S' && cmd[2] == '\0')
success = listTables("Stvs", NULL, pset, show_verbose);
success = listTables("Stvs", NULL, show_verbose);
else
success = listTables(&cmd[1], options[0], pset, show_verbose);
success = listTables(&cmd[1], options[0], show_verbose);
break;
default:
status = CMD_UNKNOWN;
@ -412,15 +416,15 @@ exec_command(const char *cmd,
/* \f -- change field separator */
else if (strcmp(cmd, "f") == 0)
success = do_pset("fieldsep", options[0], &pset->popt, quiet);
success = do_pset("fieldsep", options[0], &pset.popt, quiet);
/* \g means send query */
else if (strcmp(cmd, "g") == 0)
{
if (!options[0])
pset->gfname = NULL;
pset.gfname = NULL;
else
pset->gfname = xstrdup(options[0]);
pset.gfname = xstrdup(options[0]);
status = CMD_SEND;
}
@ -442,10 +446,10 @@ exec_command(const char *cmd,
/* HTML mode */
else if (strcmp(cmd, "H") == 0 || strcmp(cmd, "html") == 0)
{
if (pset->popt.topt.format != PRINT_HTML)
success = do_pset("format", "html", &pset->popt, quiet);
if (pset.popt.topt.format != PRINT_HTML)
success = do_pset("format", "html", &pset.popt, quiet);
else
success = do_pset("format", "aligned", &pset->popt, quiet);
success = do_pset("format", "aligned", &pset.popt, quiet);
}
@ -454,22 +458,22 @@ exec_command(const char *cmd,
{
if (!options[0])
{
if (pset->cur_cmd_interactive)
if (pset.cur_cmd_interactive)
fprintf(stderr, "\\%s: missing required argument\n", cmd);
else
fprintf(stderr, "%s: \\%s: missing required argument", pset->progname, cmd);
fprintf(stderr, "%s: \\%s: missing required argument", pset.progname, cmd);
success = false;
}
else
success = process_file(options[0], pset);
success = process_file(options[0]);
}
/* \l is list databases */
else if (strcmp(cmd, "l") == 0 || strcmp(cmd, "list") == 0)
success = listAllDbs(pset, false);
success = listAllDbs(false);
else if (strcmp(cmd, "l+") == 0 || strcmp(cmd, "list+") == 0)
success = listAllDbs(pset, true);
success = listAllDbs(true);
/* large object things */
@ -479,45 +483,45 @@ exec_command(const char *cmd,
{
if (!options[1])
{
if (pset->cur_cmd_interactive)
if (pset.cur_cmd_interactive)
fprintf(stderr, "\\%s: missing required argument", cmd);
else
fprintf(stderr, "%s: \\%s: missing required argument", pset->progname, cmd);
fprintf(stderr, "%s: \\%s: missing required argument", pset.progname, cmd);
success = false;
}
else
success = do_lo_export(pset, options[0], options[1]);
success = do_lo_export(options[0], options[1]);
}
else if (strcmp(cmd + 3, "import") == 0)
{
if (!options[0])
{
if (pset->cur_cmd_interactive)
if (pset.cur_cmd_interactive)
fprintf(stderr, "\\%s: missing required argument", cmd);
else
fprintf(stderr, "%s: \\%s: missing required argument", pset->progname, cmd);
fprintf(stderr, "%s: \\%s: missing required argument", pset.progname, cmd);
success = false;
}
else
success = do_lo_import(pset, options[0], options[1]);
success = do_lo_import(options[0], options[1]);
}
else if (strcmp(cmd + 3, "list") == 0)
success = do_lo_list(pset);
success = do_lo_list();
else if (strcmp(cmd + 3, "unlink") == 0)
{
if (!options[0])
{
if (pset->cur_cmd_interactive)
if (pset.cur_cmd_interactive)
fprintf(stderr, "\\%s: missing required argument", cmd);
else
fprintf(stderr, "%s: \\%s: missing required argument", pset->progname, cmd);
fprintf(stderr, "%s: \\%s: missing required argument", pset.progname, cmd);
success = false;
}
else
success = do_lo_unlink(pset, options[0]);
success = do_lo_unlink(options[0]);
}
else
@ -526,7 +530,7 @@ exec_command(const char *cmd,
/* \o -- set query output */
else if (strcmp(cmd, "o") == 0 || strcmp(cmd, "out") == 0)
success = setQFout(options[0], pset);
success = setQFout(options[0]);
/* \p prints the current query buffer */
@ -544,14 +548,14 @@ exec_command(const char *cmd,
{
if (!options[0])
{
if (pset->cur_cmd_interactive)
if (pset.cur_cmd_interactive)
fprintf(stderr, "\\%s: missing required argument", cmd);
else
fprintf(stderr, "%s: \\%s: missing required argument", pset->progname, cmd);
fprintf(stderr, "%s: \\%s: missing required argument", pset.progname, cmd);
success = false;
}
else
success = do_pset(options[0], options[1], &pset->popt, quiet);
success = do_pset(options[0], options[1], &pset.popt, quiet);
}
/* \q or \quit */
@ -564,8 +568,8 @@ exec_command(const char *cmd,
int i;
for (i = 0; i < 16 && options[i]; i++)
fputs(options[i], pset->queryFout);
fputs("\n", pset->queryFout);
fputs(options[i], pset.queryFout);
fputs("\n", pset.queryFout);
}
/* reset(clear) the buffer */
@ -607,18 +611,21 @@ exec_command(const char *cmd,
*/
struct _variable *ptr;
for (ptr = pset->vars; ptr->next; ptr = ptr->next)
for (ptr = pset.vars; ptr->next; ptr = ptr->next)
fprintf(stdout, "%s = '%s'\n", ptr->next->name, ptr->next->value);
success = true;
}
else
{
if (!SetVariable(pset->vars, options[0], options[1]))
const char * val = options[1];
if (!val)
val = "";
if (!SetVariable(pset.vars, options[0], val))
{
if (pset->cur_cmd_interactive)
fprintf(stderr, "\\%s: failed\n", cmd);
if (pset.cur_cmd_interactive)
fprintf(stderr, "\\%s: error\n", cmd);
else
fprintf(stderr, "%s: \\%s: failed\n", pset->progname, cmd);
fprintf(stderr, "%s: \\%s: error\n", pset.progname, cmd);
success = false;
}
@ -627,13 +634,26 @@ exec_command(const char *cmd,
/* \t -- turn off headers and row count */
else if (strcmp(cmd, "t") == 0)
success = do_pset("tuples_only", NULL, &pset->popt, quiet);
success = do_pset("tuples_only", NULL, &pset.popt, quiet);
/* \T -- define html <table ...> attributes */
else if (strcmp(cmd, "T") == 0)
success = do_pset("tableattr", options[0], &pset->popt, quiet);
success = do_pset("tableattr", options[0], &pset.popt, quiet);
/* \unset */
else if (strcmp(cmd, "unset") == 0)
{
if (!SetVariable(pset.vars, options[0], NULL))
{
if (pset.cur_cmd_interactive)
fprintf(stderr, "\\%s: error\n", cmd);
else
fprintf(stderr, "%s: \\%s: error\n", pset.progname, cmd);
success = false;
}
}
/* \w -- write query buffer to file */
else if (strcmp(cmd, "w") == 0 || strcmp(cmd, "write") == 0)
@ -643,10 +663,10 @@ exec_command(const char *cmd,
if (!options[0])
{
if (pset->cur_cmd_interactive)
if (pset.cur_cmd_interactive)
fprintf(stderr, "\\%s: missing required argument", cmd);
else
fprintf(stderr, "%s: \\%s: missing required argument", pset->progname, cmd);
fprintf(stderr, "%s: \\%s: missing required argument", pset.progname, cmd);
success = false;
}
else
@ -698,19 +718,19 @@ exec_command(const char *cmd,
/* \x -- toggle expanded table representation */
else if (strcmp(cmd, "x") == 0)
success = do_pset("expanded", NULL, &pset->popt, quiet);
success = do_pset("expanded", NULL, &pset.popt, quiet);
/* list table rights (grant/revoke) */
else if (strcmp(cmd, "z") == 0)
success = permissionsList(options[0], pset);
success = permissionsList(options[0]);
else if (strcmp(cmd, "!") == 0)
success = do_shell(options_string);
else if (strcmp(cmd, "?") == 0)
slashUsage(pset);
slashUsage();
#ifdef NOT_USED
@ -748,7 +768,7 @@ exec_command(const char *cmd,
* The return value is malloc()'ed.
*/
static char *
unescape(const char *source, PsqlSettings *pset)
unescape(const char *source)
{
unsigned char *p;
bool esc = false; /* Last character we saw was the escape
@ -831,8 +851,9 @@ unescape(const char *source, PsqlSettings *pset)
len = strcspn(p + 2, "}");
copy = xstrdup(p + 2);
copy[len] = '\0';
value = interpolate_var(copy, pset);
value = GetVariable(pset.vars, copy);
if (!value)
value = "";
length += strlen(value) - (len + 3);
new = realloc(destination, length);
if (!new)
@ -871,40 +892,42 @@ unescape(const char *source, PsqlSettings *pset)
*
* Connects to a database (new_dbname) as a certain user (new_user).
* The new user can be NULL. A db name of "-" is the same as the old one.
* (That is, the one currently in pset. But pset->db can also be NULL. A NULL
* (That is, the one currently in pset. But pset.db can also be NULL. A NULL
* dbname is handled by libpq.)
* Returns true if all ok, false if the new connection couldn't be established
* but the old one was set back. Otherwise it terminates the program.
*/
static bool
do_connect(const char *new_dbname, const char *new_user, PsqlSettings *pset)
do_connect(const char *new_dbname, const char *new_user)
{
PGconn *oldconn = pset->db;
PGconn *oldconn = pset.db;
const char *dbparam = NULL;
const char *userparam = NULL;
const char *pwparam = NULL;
char *prompted_password = NULL;
char *prompted_user = NULL;
bool need_pass;
bool success = false;
/* Delete variables (in case we fail before setting them anew) */
SetVariable(pset.vars, "DBNAME", NULL);
SetVariable(pset.vars, "USER", NULL);
SetVariable(pset.vars, "HOST", NULL);
SetVariable(pset.vars, "PORT", NULL);
/* If dbname is "-" then use old name, else new one (even if NULL) */
if (new_dbname && PQdb(oldconn) && (strcmp(new_dbname, "-") == 0 || strcmp(new_dbname, PQdb(oldconn)) == 0))
if (oldconn && new_dbname && PQdb(oldconn) && strcmp(new_dbname, "-") == 0)
dbparam = PQdb(oldconn);
else
dbparam = new_dbname;
/* If user is "" or "-" then use the old one */
if (new_user && PQuser(oldconn) && (strcmp(new_user, "") == 0 || strcmp(new_user, "-") == 0 || strcmp(new_user, PQuser(oldconn)) == 0))
/* If user is "" then use the old one */
if (new_user && PQuser(oldconn) && strcmp(new_user, "")==0)
userparam = PQuser(oldconn);
/* If username is "?" then prompt */
else if (new_user && strcmp(new_user, "?") == 0)
userparam = prompted_user = simple_prompt("Username: ", 100, true); /* save for free() */
else
userparam = new_user;
/* need to prompt for password? */
if (pset->getPassword)
if (pset.getPassword)
pwparam = prompted_password = simple_prompt("Password: ", 100, false); /* need to save for
* free() */
@ -912,7 +935,7 @@ do_connect(const char *new_dbname, const char *new_user, PsqlSettings *pset)
* Use old password if no new one given (if you didn't have an old
* one, fine)
*/
if (!pwparam)
if (!pwparam && oldconn)
pwparam = PQpass(oldconn);
@ -925,18 +948,18 @@ do_connect(const char *new_dbname, const char *new_user, PsqlSettings *pset)
* the default PGCLIENTENCODING value. -- 1998/12/12 Tatsuo Ishii
*/
if (!pset->has_client_encoding)
if (!pset.has_client_encoding)
putenv("PGCLIENTENCODING=");
#endif
do
{
need_pass = false;
pset->db = PQsetdbLogin(PQhost(oldconn), PQport(oldconn),
pset.db = PQsetdbLogin(PQhost(oldconn), PQport(oldconn),
NULL, NULL, dbparam, userparam, pwparam);
if (PQstatus(pset->db) == CONNECTION_BAD &&
strcmp(PQerrorMessage(pset->db), "fe_sendauth: no password supplied\n") == 0)
if (PQstatus(pset.db) == CONNECTION_BAD &&
strcmp(PQerrorMessage(pset.db), "fe_sendauth: no password supplied\n") == 0)
{
need_pass = true;
free(prompted_password);
@ -946,40 +969,39 @@ do_connect(const char *new_dbname, const char *new_user, PsqlSettings *pset)
} while (need_pass);
free(prompted_password);
free(prompted_user);
/*
* If connection failed, try at least keep the old one. That's
* probably more convenient than just kicking you out of the program.
*/
if (!pset->db || PQstatus(pset->db) == CONNECTION_BAD)
if (!pset.db || PQstatus(pset.db) == CONNECTION_BAD)
{
if (pset->cur_cmd_interactive)
if (pset.cur_cmd_interactive)
{
fprintf(stderr, "\\connect: %s", PQerrorMessage(pset->db));
PQfinish(pset->db);
fprintf(stderr, "%s", PQerrorMessage(pset.db));
PQfinish(pset.db);
if (oldconn)
{
fputs("Previous connection kept\n", stderr);
pset->db = oldconn;
pset.db = oldconn;
}
else
pset->db = NULL;
pset.db = NULL;
}
else
{
/* we don't want unpredictable things to
* happen in scripting mode */
fprintf(stderr, "%s: \\connect: %s", pset->progname, PQerrorMessage(pset->db));
PQfinish(pset->db);
fprintf(stderr, "%s: \\connect: %s", pset.progname, PQerrorMessage(pset.db));
PQfinish(pset.db);
if (oldconn)
PQfinish(oldconn);
pset->db = NULL;
pset.db = NULL;
}
}
else
{
if (!GetVariable(pset->vars, "quiet"))
if (!QUIET())
{
if (userparam != new_user) /* no new user */
printf("You are now connected to database %s.\n", dbparam);
@ -987,7 +1009,7 @@ do_connect(const char *new_dbname, const char *new_user, PsqlSettings *pset)
printf("You are now connected as new user %s.\n", new_user);
else /* both new */
printf("You are now connected to database %s as user %s.\n",
PQdb(pset->db), PQuser(pset->db));
PQdb(pset.db), PQuser(pset.db));
}
if (oldconn)
@ -996,6 +1018,12 @@ do_connect(const char *new_dbname, const char *new_user, PsqlSettings *pset)
success = true;
}
/* Update variables */
SetVariable(pset.vars, "DBNAME", PQdb(pset.db));
SetVariable(pset.vars, "USER", PQuser(pset.db));
SetVariable(pset.vars, "HOST", PQhost(pset.db));
SetVariable(pset.vars, "PORT", PQport(pset.db));
return success;
}
@ -1191,7 +1219,7 @@ do_edit(const char *filename_arg, PQExpBuffer query_buf)
* Handler for \i, but can be used for other things as well.
*/
bool
process_file(const char *filename, PsqlSettings *pset)
process_file(const char *filename)
{
FILE *fd;
int result;
@ -1207,11 +1235,13 @@ process_file(const char *filename, PsqlSettings *pset)
if (!fd)
{
if (!pset.cur_cmd_interactive)
fprintf(stderr, "%s: ", pset.progname);
perror(filename);
return false;
}
result = MainLoop(pset, fd);
result = MainLoop(fd);
fclose(fd);
return (result == EXIT_SUCCESS);
}

View File

@ -24,19 +24,18 @@ typedef enum _backslashResult
backslashResult HandleSlashCmds(PsqlSettings *pset,
const char *line,
backslashResult
HandleSlashCmds(const char *line,
PQExpBuffer query_buf,
const char **end_of_cmd);
bool process_file(const char *filename,
PsqlSettings *pset);
bool
process_file(const char *filename);
bool do_pset(const char *param,
bool
do_pset(const char *param,
const char *value,
printQueryOpt * popt,
bool quiet);
#endif

View File

@ -1,7 +1,7 @@
#include <config.h>
#include <c.h>
#include "common.h"
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@ -12,7 +12,6 @@
#include <strdup.h>
#endif
#include <signal.h>
#include <assert.h>
#ifndef WIN32
#include <unistd.h> /* for write() */
#else
@ -73,64 +72,46 @@ xstrdup(const char *string)
* Upon failure, sets stdout and returns false.
*/
bool
setQFout(const char *fname, PsqlSettings *pset)
setQFout(const char *fname)
{
bool status = true;
#ifdef USE_ASSERT_CHECKING
assert(pset);
#else
if (!pset)
return false;
#endif
/* Close old file/pipe */
if (pset->queryFout && pset->queryFout != stdout && pset->queryFout != stderr)
if (pset.queryFout && pset.queryFout != stdout && pset.queryFout != stderr)
{
if (pset->queryFoutPipe)
pclose(pset->queryFout);
if (pset.queryFoutPipe)
pclose(pset.queryFout);
else
fclose(pset->queryFout);
fclose(pset.queryFout);
}
/* If no filename, set stdout */
if (!fname || fname[0] == '\0')
{
pset->queryFout = stdout;
pset->queryFoutPipe = false;
pset.queryFout = stdout;
pset.queryFoutPipe = false;
}
else if (*fname == '|')
{
const char *pipename = fname + 1;
#ifndef __CYGWIN32__
pset->queryFout = popen(pipename, "w");
#else
pset->queryFout = popen(pipename, "wb");
#endif
pset->queryFoutPipe = true;
pset.queryFout = popen(fname + 1, "w");
pset.queryFoutPipe = true;
}
else
{
#ifndef __CYGWIN32__
pset->queryFout = fopen(fname, "w");
#else
pset->queryFout = fopen(fname, "wb");
#endif
pset->queryFoutPipe = false;
pset.queryFout = fopen(fname, "w");
pset.queryFoutPipe = false;
}
if (!pset->queryFout)
if (!(pset.queryFout))
{
perror(fname);
pset->queryFout = stdout;
pset->queryFoutPipe = false;
fprintf(stderr, "%s: %s: %s\n", pset.progname, fname, strerror(errno));
pset.queryFout = stdout;
pset.queryFoutPipe = false;
status = false;
}
/* Direct signals */
if (pset->queryFoutPipe)
if (pset.queryFoutPipe)
pqsignal(SIGPIPE, SIG_IGN);
else
pqsignal(SIGPIPE, SIG_DFL);
@ -211,93 +192,6 @@ simple_prompt(const char *prompt, int maxlen, bool echo)
/*
* interpolate_var()
*
* The idea here is that certain variables have a "magic" meaning, such as
* LastOid. However, you can assign to those variables, but that will shadow
* the magic meaning, until you unset it. If nothing matches, the value of
* the environment variable is used.
*
* This function only returns NULL if you feed in NULL's (don't do that).
* Otherwise, the return value is ready for immediate consumption.
*/
const char *
interpolate_var(const char *name, PsqlSettings *pset)
{
const char *var;
#ifdef USE_ASSERT_CHECKING
assert(name);
assert(pset);
#else
if (!name || !pset)
return NULL;
#endif
var = GetVariable(pset->vars, name);
if (var)
return var;
/* otherwise return magic variable */
/*
* (by convention these should be capitalized (but not all caps), to
* not be shadowed by regular vars or to shadow env vars)
*/
if (strcmp(name, "Version") == 0)
return PG_VERSION_STR;
if (strcmp(name, "Database") == 0)
{
if (PQdb(pset->db))
return PQdb(pset->db);
else
return "";
}
if (strcmp(name, "User") == 0)
{
if (PQuser(pset->db))
return PQuser(pset->db);
else
return "";
}
if (strcmp(name, "Host") == 0)
{
if (PQhost(pset->db))
return PQhost(pset->db);
else
return "";
}
if (strcmp(name, "Port") == 0)
{
if (PQport(pset->db))
return PQport(pset->db);
else
return "";
}
if (strcmp(name, "LastOid") == 0)
{
static char buf[24];
if (pset->lastOid == InvalidOid)
return "";
sprintf(buf, "%u", pset->lastOid);
return buf;
}
/* env vars */
if ((var = getenv(name)))
return var;
return "";
}
/*
* Code to support query cancellation
*
@ -333,21 +227,21 @@ handle_sigint(SIGNAL_ARGS)
* PSQLexec
*
* This is the way to send "backdoor" queries (those not directly entered
* by the user). It is subject to -E (echo_secret) but not -e (echo).
* by the user). It is subject to -E but not -e.
*/
PGresult *
PSQLexec(PsqlSettings *pset, const char *query)
PSQLexec(const char *query)
{
PGresult *res;
const char *var;
if (!pset->db)
if (!pset.db)
{
fputs("You are currently not connected to a database.\n", stderr);
return NULL;
}
var = GetVariable(pset->vars, "echo_secret");
var = GetVariable(pset.vars, "ECHO_HIDDEN");
if (var)
{
printf("********* QUERY *********\n%s\n*************************\n\n", query);
@ -357,50 +251,50 @@ PSQLexec(PsqlSettings *pset, const char *query)
if (var && strcmp(var, "noexec") == 0)
return NULL;
cancelConn = pset->db;
cancelConn = pset.db;
pqsignal(SIGINT, handle_sigint); /* control-C => cancel */
res = PQexec(pset->db, query);
res = PQexec(pset.db, query);
pqsignal(SIGINT, SIG_DFL); /* now control-C is back to normal */
if (PQstatus(pset->db) == CONNECTION_OK)
if (PQstatus(pset.db) == CONNECTION_BAD)
{
if (res && (PQresultStatus(res) == PGRES_COMMAND_OK ||
PQresultStatus(res) == PGRES_TUPLES_OK ||
PQresultStatus(res) == PGRES_COPY_IN ||
PQresultStatus(res) == PGRES_COPY_OUT)
)
return res; /* Normal success case... */
/* Normal failure case --- display error and return NULL */
fputs(PQerrorMessage(pset->db), pset->queryFout);
if (!pset.cur_cmd_interactive)
{
fprintf(stderr, "%s: connection to server was lost", pset.progname);
exit(EXIT_BADCONN);
}
fputs("The connection to the server was lost. Attempting reset: ", stderr);
PQreset(pset.db);
if (PQstatus(pset.db) == CONNECTION_BAD)
{
fputs("Failed.\n", stderr);
PQfinish(pset.db);
PQclear(res);
pset.db = NULL;
SetVariable(pset.vars, "DBNAME", NULL);
SetVariable(pset.vars, "HOST", NULL);
SetVariable(pset.vars, "PORT", NULL);
SetVariable(pset.vars, "USER", NULL);
return NULL;
}
else
fputs("Succeeded.\n", stderr);
}
if (res && (PQresultStatus(res) == PGRES_COMMAND_OK ||
PQresultStatus(res) == PGRES_TUPLES_OK ||
PQresultStatus(res) == PGRES_COPY_IN ||
PQresultStatus(res) == PGRES_COPY_OUT)
)
return res;
else
{
fputs(PQerrorMessage(pset.db), stderr);
PQclear(res);
return NULL;
}
/* Lost connection. Report whatever libpq has to say,
* then consider recovery.
*/
fputs(PQerrorMessage(pset->db), pset->queryFout);
PQclear(res);
if (!pset->cur_cmd_interactive)
{
fprintf(stderr, "%s: connection to server was lost\n",
pset->progname);
exit(EXIT_BADCONN);
}
fputs("The connection to the server was lost. Attempting reset: ", stderr);
fflush(stderr);
PQreset(pset->db);
if (PQstatus(pset->db) == CONNECTION_BAD)
{
fputs("Failed.\n", stderr);
PQfinish(pset->db);
pset->db = NULL;
}
else
fputs("Succeeded.\n", stderr);
return NULL;
}
@ -418,19 +312,19 @@ PSQLexec(PsqlSettings *pset, const char *query)
* Returns true if the query executed successfully, false otherwise.
*/
bool
SendQuery(PsqlSettings *pset, const char *query)
SendQuery(const char *query)
{
bool success = false;
PGresult *results;
PGnotify *notify;
if (!pset->db)
if (!pset.db)
{
fputs("You are currently not connected to a database.\n", stderr);
return false;
}
if (GetVariableBool(pset->vars, "singlestep"))
if (GetVariableBool(pset.vars, "SINGLESTEP"))
{
char buf[3];
@ -443,17 +337,23 @@ SendQuery(PsqlSettings *pset, const char *query)
if (buf[0] == 'x')
return false;
}
else
{
const char * var = GetVariable(pset.vars, "ECHO");
if (var && strcmp(var, "brief")==0)
puts(query);
}
cancelConn = pset->db;
cancelConn = pset.db;
pqsignal(SIGINT, handle_sigint);
results = PQexec(pset->db, query);
results = PQexec(pset.db, query);
pqsignal(SIGINT, SIG_DFL);
if (results == NULL)
{
fputs(PQerrorMessage(pset->db), pset->queryFout);
fputs(PQerrorMessage(pset.db), pset.queryFout);
success = false;
}
else
@ -461,24 +361,30 @@ SendQuery(PsqlSettings *pset, const char *query)
switch (PQresultStatus(results))
{
case PGRES_TUPLES_OK:
if (pset->gfname)
/* write output to \g argument, if any */
if (pset.gfname)
{
PsqlSettings settings_copy = *pset;
FILE * queryFout_copy = pset.queryFout;
bool queryFoutPipe_copy = pset.queryFoutPipe;
pset.queryFout = NULL; /* so it doesn't get closed */
settings_copy.queryFout = stdout;
if (!setQFout(pset->gfname, &settings_copy))
/* open file/pipe */
if (!setQFout(pset.gfname))
{
success = false;
break;
}
printQuery(results, &settings_copy.popt, settings_copy.queryFout);
printQuery(results, &pset.popt, pset.queryFout);
/* close file/pipe */
setQFout(NULL, &settings_copy);
setQFout(NULL);
free(pset->gfname);
pset->gfname = NULL;
free(pset.gfname);
pset.gfname = NULL;
pset.queryFout = queryFout_copy;
pset.queryFoutPipe = queryFoutPipe_copy;
success = true;
break;
@ -486,77 +392,83 @@ SendQuery(PsqlSettings *pset, const char *query)
else
{
success = true;
printQuery(results, &pset->popt, pset->queryFout);
printQuery(results, &pset.popt, pset.queryFout);
}
break;
case PGRES_EMPTY_QUERY:
success = true;
break;
case PGRES_COMMAND_OK:
success = true;
pset->lastOid = PQoidValue(results);
if (!GetVariableBool(pset->vars, "quiet"))
fprintf(pset->queryFout, "%s\n", PQcmdStatus(results));
break;
{
char buf[10];
success = true;
sprintf(buf, "%u", (unsigned int)PQoidValue(results));
if (!QUIET())
fprintf(pset.queryFout, "%s\n", PQcmdStatus(results));
SetVariable(pset.vars, "LASTOID", buf);
break;
}
case PGRES_COPY_OUT:
success = handleCopyOut(pset->db, pset->queryFout);
success = handleCopyOut(pset.db, pset.queryFout);
break;
case PGRES_COPY_IN:
if (pset->cur_cmd_interactive && !GetVariable(pset->vars, "quiet"))
if (pset.cur_cmd_interactive && !QUIET())
puts("Enter data to be copied followed by a newline.\n"
"End with a backslash and a period on a line by itself.");
success = handleCopyIn(pset->db, pset->cur_cmd_source,
pset->cur_cmd_interactive ? get_prompt(pset, PROMPT_COPY) : NULL);
success = handleCopyIn(pset.db, pset.cur_cmd_source,
pset.cur_cmd_interactive ? get_prompt(PROMPT_COPY) : NULL);
break;
case PGRES_NONFATAL_ERROR:
case PGRES_FATAL_ERROR:
case PGRES_BAD_RESPONSE:
success = false;
fputs(PQerrorMessage(pset->db), stderr);
fputs(PQerrorMessage(pset.db), stderr);
break;
}
fflush(pset->queryFout);
fflush(pset.queryFout);
if (PQstatus(pset->db) == CONNECTION_BAD)
if (PQstatus(pset.db) == CONNECTION_BAD)
{
if (!pset->cur_cmd_interactive)
if (!pset.cur_cmd_interactive)
{
fprintf(stderr, "%s: connection to server was lost\n",
pset->progname);
fprintf(stderr, "%s: connection to server was lost", pset.progname);
exit(EXIT_BADCONN);
}
fputs("The connection to the server was lost. Attempting reset: ", stderr);
fflush(stderr);
PQreset(pset->db);
if (PQstatus(pset->db) == CONNECTION_BAD)
PQreset(pset.db);
if (PQstatus(pset.db) == CONNECTION_BAD)
{
fputs("Failed.\n", stderr);
PQfinish(pset->db);
pset->db = NULL;
PQfinish(pset.db);
PQclear(results);
pset.db = NULL;
SetVariable(pset.vars, "DBNAME", NULL);
SetVariable(pset.vars, "HOST", NULL);
SetVariable(pset.vars, "PORT", NULL);
SetVariable(pset.vars, "USER", NULL);
return false;
}
else
fputs("Succeeded.\n", stderr);
}
/* check for asynchronous notification returns */
while ((notify = PQnotifies(pset->db)) != NULL)
while ((notify = PQnotifies(pset.db)) != NULL)
{
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);
free(notify);
fflush(pset->queryFout);
fflush(pset.queryFout);
}
if (results)
PQclear(results);
}
}
return success;
}

View File

@ -8,18 +8,15 @@ char *
xstrdup(const char *string);
bool
setQFout(const char *fname, PsqlSettings *pset);
setQFout(const char *fname);
char *
simple_prompt(const char *prompt, int maxlen, bool echo);
const char *
interpolate_var(const char *name, PsqlSettings *pset);
PGresult *
PSQLexec(PsqlSettings *pset, const char *query);
PSQLexec(const char *query);
bool
SendQuery(PsqlSettings *pset, const char *query);
SendQuery(const char *query);
#endif /* COMMON_H */

View File

@ -1,4 +1,3 @@
#include <config.h>
#include <c.h>
#include "copy.h"
@ -36,7 +35,7 @@
struct copy_options
{
char *table;
char *file;
char *file; /* NULL = stdin/stdout */
bool from;
bool binary;
bool oids;
@ -59,7 +58,7 @@ free_copy_options(struct copy_options * ptr)
static struct copy_options *
parse_slash_copy(const char *args, PsqlSettings *pset)
parse_slash_copy(const char *args)
{
struct copy_options *result;
char *line;
@ -132,17 +131,15 @@ parse_slash_copy(const char *args, PsqlSettings *pset)
if (!error)
{
token = strtokx(NULL, " \t", "'", '\\', NULL, NULL);
token = strtokx(NULL, " \t", "'", '\\', &quote, NULL);
if (!token)
error = true;
else
else if (!quote && (strcasecmp(token, "stdin")==0 || strcasecmp(token, "stdout")==0))
result->file = NULL;
else
result->file = xstrdup(token);
}
#ifdef USE_ASSERT_CHECKING
assert(error || result->file);
#endif
if (!error)
{
token = strtokx(NULL, " \t", NULL, '\\', NULL, NULL);
@ -194,8 +191,8 @@ parse_slash_copy(const char *args, PsqlSettings *pset)
if (error)
{
if (!pset->cur_cmd_interactive)
fprintf(stderr, "%s: ", pset->progname);
if (!pset.cur_cmd_interactive)
fprintf(stderr, "%s: ", pset.progname);
fputs("\\copy: parse error at ", stderr);
if (!token)
fputs("end of line", stderr);
@ -217,7 +214,7 @@ parse_slash_copy(const char *args, PsqlSettings *pset)
* file or route its response into the file.
*/
bool
do_copy(const char *args, PsqlSettings *pset)
do_copy(const char *args)
{
char query[128 + NAMEDATALEN];
FILE *copystream;
@ -226,7 +223,7 @@ do_copy(const char *args, PsqlSettings *pset)
bool success;
/* parse options */
options = parse_slash_copy(args, pset);
options = parse_slash_copy(args);
if (!options)
return false;
@ -242,9 +239,9 @@ do_copy(const char *args, PsqlSettings *pset)
strcat(query, "WITH OIDS ");
if (options->from)
strcat(query, "FROM stdin");
strcat(query, "FROM STDIN");
else
strcat(query, "TO stdout");
strcat(query, "TO STDOUT");
if (options->delim)
@ -254,24 +251,32 @@ do_copy(const char *args, PsqlSettings *pset)
strcat(query, "'");
}
if (options->null)
{
strcat(query, " WITH NULL AS '");
strcat(query, options->null);
strcat(query, "'");
}
if (options->from)
#ifndef __CYGWIN32__
copystream = fopen(options->file, "r");
#else
copystream = fopen(options->file, "rb");
#endif
{
if (options->file)
copystream = fopen(options->file, "r");
else
copystream = stdin;
}
else
#ifndef __CYGWIN32__
copystream = fopen(options->file, "w");
#else
copystream = fopen(options->file, "wb");
#endif
{
if (options->file)
copystream = fopen(options->file, "w");
else
copystream = stdout;
}
if (!copystream)
{
if (!pset->cur_cmd_interactive)
fprintf(stderr, "%s: ", pset->progname);
if (!pset.cur_cmd_interactive)
fprintf(stderr, "%s: ", pset.progname);
fprintf(stderr,
"unable to open file %s: %s\n",
options->file, strerror(errno));
@ -279,40 +284,40 @@ do_copy(const char *args, PsqlSettings *pset)
return false;
}
result = PSQLexec(pset, query);
result = PSQLexec(query);
switch (PQresultStatus(result))
{
case PGRES_COPY_OUT:
success = handleCopyOut(pset->db, copystream);
success = handleCopyOut(pset.db, copystream);
break;
case PGRES_COPY_IN:
success = handleCopyIn(pset->db, copystream, NULL);
success = handleCopyIn(pset.db, copystream, NULL);
break;
case PGRES_NONFATAL_ERROR:
case PGRES_FATAL_ERROR:
case PGRES_BAD_RESPONSE:
success = false;
fputs(PQerrorMessage(pset->db), stderr);
fputs(PQerrorMessage(pset.db), stderr);
break;
default:
success = false;
if (!pset->cur_cmd_interactive)
fprintf(stderr, "%s: ", pset->progname);
if (!pset.cur_cmd_interactive)
fprintf(stderr, "%s: ", pset.progname);
fprintf(stderr, "\\copy: unexpected response (%d)\n", PQresultStatus(result));
}
PQclear(result);
if (!GetVariable(pset->vars, "quiet"))
if (!success)
{
if (success)
puts("Successfully copied");
else
puts("Copy failed");
if (!pset.cur_cmd_interactive)
fprintf(stderr, "%s: ", pset.progname);
fprintf(stderr, "\\copy failed\n");
}
fclose(copystream);
if (copystream != stdout && copystream != stdin)
fclose(copystream);
free_copy_options(options);
return success;
}
@ -396,7 +401,7 @@ handleCopyIn(PGconn *conn, FILE *copystream, const char *prompt)
while (!copydone)
{ /* for each input line ... */
if (prompt && isatty(fileno(stdin)))
if (prompt && isatty(fileno(copystream)))
{
fputs(prompt, stdout);
fflush(stdout);

View File

@ -8,7 +8,7 @@
/* handler for \copy */
bool
do_copy(const char *args, PsqlSettings *pset);
do_copy(const char *args);
/* lower level processors for copy in/out streams */

View File

@ -31,11 +31,11 @@
* takes an optional regexp to match specific aggregates by name
*/
bool
describeAggregates(const char *name, PsqlSettings *pset)
describeAggregates(const char *name)
{
char buf[384 + 2 * REGEXP_CUTOFF];
PGresult *res;
printQueryOpt myopt = pset->popt;
printQueryOpt myopt = pset.popt;
/*
* There are two kinds of aggregates: ones that work on particular
@ -72,14 +72,14 @@ describeAggregates(const char *name, PsqlSettings *pset)
strcat(buf, "ORDER BY \"Name\", \"Type\"");
res = PSQLexec(pset, buf);
res = PSQLexec(buf);
if (!res)
return false;
myopt.nullPrint = NULL;
myopt.title = "List of aggregates";
printQuery(res, &myopt, pset->queryFout);
printQuery(res, &myopt, pset.queryFout);
PQclear(res);
return true;
@ -90,11 +90,11 @@ describeAggregates(const char *name, PsqlSettings *pset)
* Takes an optional regexp to narrow down the function name
*/
bool
describeFunctions(const char *name, PsqlSettings *pset, bool verbose)
describeFunctions(const char *name, bool verbose)
{
char buf[384 + REGEXP_CUTOFF];
PGresult *res;
printQueryOpt myopt = pset->popt;
printQueryOpt myopt = pset.popt;
/*
* we skip in/out funcs by excluding functions that take some
@ -125,14 +125,14 @@ describeFunctions(const char *name, PsqlSettings *pset, bool verbose)
}
strcat(buf, "ORDER BY \"Function\", \"Result\", \"Arguments\"");
res = PSQLexec(pset, buf);
res = PSQLexec(buf);
if (!res)
return false;
myopt.nullPrint = NULL;
myopt.title = "List of functions";
printQuery(res, &myopt, pset->queryFout);
printQuery(res, &myopt, pset.queryFout);
PQclear(res);
return true;
@ -145,11 +145,11 @@ describeFunctions(const char *name, PsqlSettings *pset, bool verbose)
* describe types
*/
bool
describeTypes(const char *name, PsqlSettings *pset, bool verbose)
describeTypes(const char *name, bool verbose)
{
char buf[256 + REGEXP_CUTOFF];
PGresult *res;
printQueryOpt myopt = pset->popt;
printQueryOpt myopt = pset.popt;
strcpy(buf, "SELECT t.typname AS \"Type\"");
if (verbose)
@ -169,14 +169,14 @@ describeTypes(const char *name, PsqlSettings *pset, bool verbose)
}
strcat(buf, "ORDER BY t.typname;");
res = PSQLexec(pset, buf);
res = PSQLexec(buf);
if (!res)
return false;
myopt.nullPrint = NULL;
myopt.title = "List of types";
printQuery(res, &myopt, pset->queryFout);
printQuery(res, &myopt, pset.queryFout);
PQclear(res);
return true;
@ -187,11 +187,11 @@ describeTypes(const char *name, PsqlSettings *pset, bool verbose)
/* \do
*/
bool
describeOperators(const char *name, PsqlSettings *pset)
describeOperators(const char *name)
{
char buf[1536 + 3 * REGEXP_CUTOFF];
PGresult *res;
printQueryOpt myopt = pset->popt;
printQueryOpt myopt = pset.popt;
strcpy(buf,
"SELECT o.oprname AS \"Op\",\n"
@ -251,14 +251,14 @@ describeOperators(const char *name, PsqlSettings *pset)
}
strcat(buf, "\nORDER BY \"Op\", \"Left arg\", \"Right arg\", \"Result\"");
res = PSQLexec(pset, buf);
res = PSQLexec(buf);
if (!res)
return false;
myopt.nullPrint = NULL;
myopt.title = "List of operators";
printQuery(res, &myopt, pset->queryFout);
printQuery(res, &myopt, pset.queryFout);
PQclear(res);
return true;
@ -271,11 +271,11 @@ describeOperators(const char *name, PsqlSettings *pset)
* for \l, \list, and -l switch
*/
bool
listAllDbs(PsqlSettings *pset, bool desc)
listAllDbs(bool desc)
{
PGresult *res;
char buf[512];
printQueryOpt myopt = pset->popt;
printQueryOpt myopt = pset.popt;
strcpy(buf,
"SELECT pg_database.datname as \"Database\",\n"
@ -306,14 +306,14 @@ listAllDbs(PsqlSettings *pset, bool desc)
strcat(buf, "ORDER BY \"Database\"");
res = PSQLexec(pset, buf);
res = PSQLexec(buf);
if (!res)
return false;
myopt.nullPrint = NULL;
myopt.title = "List of databases";
printQuery(res, &myopt, pset->queryFout);
printQuery(res, &myopt, pset.queryFout);
PQclear(res);
return true;
@ -325,11 +325,11 @@ listAllDbs(PsqlSettings *pset, bool desc)
*
*/
bool
permissionsList(const char *name, PsqlSettings *pset)
permissionsList(const char *name)
{
char descbuf[256 + REGEXP_CUTOFF];
PGresult *res;
printQueryOpt myopt = pset->popt;
printQueryOpt myopt = pset.popt;
descbuf[0] = '\0';
/* Currently, we ignore indexes since they have no meaningful rights */
@ -346,15 +346,15 @@ permissionsList(const char *name, PsqlSettings *pset)
}
strcat(descbuf, "ORDER BY relname");
res = PSQLexec(pset, descbuf);
res = PSQLexec(descbuf);
if (!res)
return false;
myopt.nullPrint = NULL;
sprintf(descbuf, "Access permissions for database \"%s\"", PQdb(pset->db));
sprintf(descbuf, "Access permissions for database \"%s\"", PQdb(pset.db));
myopt.title = descbuf;
printQuery(res, &myopt, pset->queryFout);
printQuery(res, &myopt, pset.queryFout);
PQclear(res);
return true;
@ -371,11 +371,11 @@ permissionsList(const char *name, PsqlSettings *pset)
* lists of things, there are other \d? commands.
*/
bool
objectDescription(const char *object, PsqlSettings *pset)
objectDescription(const char *object)
{
char descbuf[2048 + 7 * REGEXP_CUTOFF];
PGresult *res;
printQueryOpt myopt = pset->popt;
printQueryOpt myopt = pset.popt;
descbuf[0] = '\0';
@ -466,7 +466,7 @@ objectDescription(const char *object, PsqlSettings *pset)
strcat(descbuf, "\nORDER BY \"Name\"");
res = PSQLexec(pset, descbuf);
res = PSQLexec(descbuf);
if (!res)
return false;
@ -474,7 +474,7 @@ objectDescription(const char *object, PsqlSettings *pset)
myopt.nullPrint = NULL;
myopt.title = "Object descriptions";
printQuery(res, &myopt, pset->queryFout);
printQuery(res, &myopt, pset.queryFout);
PQclear(res);
return true;
@ -507,11 +507,11 @@ xmalloc(size_t size)
bool
describeTableDetails(const char *name, PsqlSettings *pset, bool desc)
describeTableDetails(const char *name, bool desc)
{
char buf[512 + INDEX_MAX_KEYS * NAMEDATALEN];
PGresult *res = NULL;
printTableOpt myopt = pset->popt.topt;
printTableOpt myopt = pset.popt.topt;
int i;
const char *view_def = NULL;
const char *headers[5];
@ -536,14 +536,14 @@ describeTableDetails(const char *name, PsqlSettings *pset, bool desc)
"SELECT relhasindex, relkind, relchecks, reltriggers, relhasrules\n"
"FROM pg_class WHERE relname='%s'",
name);
res = PSQLexec(pset, buf);
res = PSQLexec(buf);
if (!res)
return false;
/* Did we get anything? */
if (PQntuples(res) == 0)
{
if (!GetVariableBool(pset->vars, "quiet"))
if (!QUIET())
fprintf(stderr, "Did not find any relation named \"%s\".\n", name);
PQclear(res);
return false;
@ -587,7 +587,7 @@ describeTableDetails(const char *name, PsqlSettings *pset, bool desc)
strcat(buf, "'\n AND a.attnum > 0 AND a.attrelid = c.oid AND a.atttypid = t.oid\n"
"ORDER BY a.attnum");
res = PSQLexec(pset, buf);
res = PSQLexec(buf);
if (!res)
return false;
@ -595,7 +595,7 @@ describeTableDetails(const char *name, PsqlSettings *pset, bool desc)
if (tableinfo.hasrules) {
PGresult *result;
sprintf(buf, "SELECT definition FROM pg_views WHERE viewname = '%s'", name);
result = PSQLexec(pset, buf);
result = PSQLexec(buf);
if (!result)
{
PQclear(res);
@ -655,7 +655,7 @@ describeTableDetails(const char *name, PsqlSettings *pset, bool desc)
"WHERE c.relname = '%s' AND c.oid = d.adrelid AND d.adnum = %s",
name, PQgetvalue(res, i, 6));
result = PSQLexec(pset, buf);
result = PSQLexec(buf);
if (!result)
error = true;
else
@ -710,7 +710,7 @@ describeTableDetails(const char *name, PsqlSettings *pset, bool desc)
"WHERE i.indexrelid = c.oid AND c.relname = '%s' AND c.relam = a.oid",
name);
result = PSQLexec(pset, buf);
result = PSQLexec(buf);
if (!result)
error = true;
else
@ -750,7 +750,7 @@ describeTableDetails(const char *name, PsqlSettings *pset, bool desc)
"WHERE c.relname = '%s' AND c.oid = i.indrelid AND i.indexrelid = c2.oid\n"
"ORDER BY c2.relname",
name);
result1 = PSQLexec(pset, buf);
result1 = PSQLexec(buf);
if (!result1)
error = true;
else
@ -764,7 +764,7 @@ describeTableDetails(const char *name, PsqlSettings *pset, bool desc)
"FROM pg_relcheck r, pg_class c\n"
"WHERE c.relname='%s' AND c.oid = r.rcrelid",
name);
result2 = PSQLexec(pset, buf);
result2 = PSQLexec(buf);
if (!result2)
error = true;
else
@ -779,7 +779,7 @@ describeTableDetails(const char *name, PsqlSettings *pset, bool desc)
"FROM pg_rewrite r, pg_class c\n"
"WHERE c.relname='%s' AND c.oid = r.ev_class",
name);
result3 = PSQLexec(pset, buf);
result3 = PSQLexec(buf);
if (!result3)
error = true;
else
@ -794,7 +794,7 @@ describeTableDetails(const char *name, PsqlSettings *pset, bool desc)
"FROM pg_trigger t, pg_class c\n"
"WHERE c.relname='%s' AND c.oid = t.tgrelid",
name);
result4 = PSQLexec(pset, buf);
result4 = PSQLexec(buf);
if (!result4)
error = true;
else
@ -863,7 +863,7 @@ describeTableDetails(const char *name, PsqlSettings *pset, bool desc)
if (!error) {
myopt.tuples_only = false;
printTable(title, headers, (const char**)cells, (const char**)footers, "llll", &myopt, pset->queryFout);
printTable(title, headers, (const char**)cells, (const char**)footers, "llll", &myopt, pset.queryFout);
}
/* clean up */
@ -906,7 +906,7 @@ describeTableDetails(const char *name, PsqlSettings *pset, bool desc)
* tries to fix this the painful way, hopefully outer joins will be done sometime.
*/
bool
listTables(const char *infotype, const char *name, PsqlSettings *pset, bool desc)
listTables(const char *infotype, const char *name, bool desc)
{
bool showTables = strchr(infotype, 't') != NULL;
bool showIndices = strchr(infotype, 'i') != NULL;
@ -916,7 +916,7 @@ listTables(const char *infotype, const char *name, PsqlSettings *pset, bool desc
char buf[3072 + 8 * REGEXP_CUTOFF];
PGresult *res;
printQueryOpt myopt = pset->popt;
printQueryOpt myopt = pset.popt;
buf[0] = '\0';
@ -1093,20 +1093,24 @@ listTables(const char *infotype, const char *name, PsqlSettings *pset, bool desc
strcat(buf, "\nORDER BY \"Name\"");
res = PSQLexec(pset, buf);
res = PSQLexec(buf);
if (!res)
return false;
if (PQntuples(res) == 0)
fprintf(pset->queryFout, "No matching relations found.\n");
if (PQntuples(res) == 0 && !QUIET())
{
if (name)
fprintf(pset.queryFout, "No matching relations found.\n");
else
fprintf(pset.queryFout, "No relations found.\n");
}
else
{
myopt.topt.tuples_only = false;
myopt.nullPrint = NULL;
myopt.title = "List of relations";
printQuery(res, &myopt, pset->queryFout);
printQuery(res, &myopt, pset.queryFout);
}
PQclear(res);

View File

@ -5,30 +5,30 @@
#include "settings.h"
/* \da */
bool describeAggregates(const char *name, PsqlSettings *pset);
bool describeAggregates(const char *name);
/* \df */
bool describeFunctions(const char *name, PsqlSettings *pset, bool verbose);
bool describeFunctions(const char *name, bool verbose);
/* \dT */
bool describeTypes(const char *name, PsqlSettings *pset, bool verbose);
bool describeTypes(const char *name, bool verbose);
/* \do */
bool describeOperators(const char *name, PsqlSettings *pset);
bool describeOperators(const char *name);
/* \z (or \dp) */
bool permissionsList(const char *name, PsqlSettings *pset);
bool permissionsList(const char *name);
/* \dd */
bool objectDescription(const char *object, PsqlSettings *pset);
bool objectDescription(const char *object);
/* \d foo */
bool describeTableDetails(const char *name, PsqlSettings *pset, bool desc);
bool describeTableDetails(const char *name, bool desc);
/* \l */
bool listAllDbs(PsqlSettings *pset, bool desc);
bool listAllDbs(bool desc);
/* \dt, \di, \ds, \dS, etc. */
bool listTables(const char *infotype, const char *name, PsqlSettings *pset, bool desc);
bool listTables(const char *infotype, const char *name, bool desc);
#endif /* DESCRIBE_H */

View File

@ -149,7 +149,7 @@ struct winsize
#endif
void
slashUsage(PsqlSettings *pset)
slashUsage(void)
{
bool usePipe = false;
const char *pagerenv;
@ -157,7 +157,7 @@ slashUsage(PsqlSettings *pset)
struct winsize screen_size;
#ifdef TIOCGWINSZ
if (pset->notty == 0 &&
if (pset.notty == 0 &&
(ioctl(fileno(stdout), TIOCGWINSZ, &screen_size) == -1 ||
screen_size.ws_col == 0 ||
screen_size.ws_row == 0))
@ -169,7 +169,7 @@ slashUsage(PsqlSettings *pset)
}
#endif
if (pset->notty == 0 &&
if (pset.notty == 0 &&
(pagerenv = getenv("PAGER")) &&
(pagerenv[0] != '\0') &&
screen_size.ws_row <= 36 &&
@ -184,7 +184,7 @@ slashUsage(PsqlSettings *pset)
/* if you add/remove a line here, change the row test above */
fprintf(fout, " \\? help\n");
fprintf(fout, " \\c[onnect] [dbname|- [user|?]]\n"
" connect to new database (currently '%s')\n", PQdb(pset->db));
" connect to new database (currently '%s')\n", PQdb(pset.db));
fprintf(fout, " \\copy ... perform SQL COPY with data stream to the client machine");
fprintf(fout, " \\copyright show PostgreSQL usage and distribution terms\n");
fprintf(fout, " \\d <table> describe table (or view, index, sequence)\n");
@ -209,9 +209,10 @@ slashUsage(PsqlSettings *pset)
fprintf(fout, " \\qecho <text> write text to query output stream (see \\o)\n");
fprintf(fout, " \\r reset (clear) the query buffer\n");
fprintf(fout, " \\s [fname] print history or save it in <fname>\n");
fprintf(fout, " \\set <var> [value] set/unset internal variable\n");
fprintf(fout, " \\t don't show table headers or footers (currently %s)\n", ON(pset->popt.topt.tuples_only));
fprintf(fout, " \\x toggle expanded output (currently %s)\n", ON(pset->popt.topt.expanded));
fprintf(fout, " \\set <var> <value> set internal variable\n");
fprintf(fout, " \\t don't show table headers or footers (currently %s)\n", ON(pset.popt.topt.tuples_only));
fprintf(fout, " \\unset <var> unset (delete) internal variable\n");
fprintf(fout, " \\x toggle expanded output (currently %s)\n", ON(pset.popt.topt.expanded));
fprintf(fout, " \\w <fname> write current query buffer to a file\n");
fprintf(fout, " \\z list table access permissions\n");
fprintf(fout, " \\! [cmd] shell escape or command\n");

View File

@ -5,7 +5,7 @@
void usage(void);
void slashUsage(PsqlSettings *pset);
void slashUsage(void);
void helpSQL(const char *topic);

View File

@ -29,6 +29,10 @@ char *
gets_interactive(const char *prompt)
{
char *s;
#ifdef USE_HISTORY
const char *var;
static char * prev_hist = NULL;
#endif
#ifdef USE_READLINE
if (useReadline)
@ -44,8 +48,19 @@ gets_interactive(const char *prompt)
#endif
#ifdef USE_HISTORY
if (useHistory && s && s[0] != '\0')
add_history(s);
if (useHistory && s && s[0] != '\0')
{
var = GetVariable(pset.vars, "HISTCONTROL");
if (!var || (var
&& !((strcmp(var, "ignorespace") == 0 || strcmp(var, "ignoreboth") ==0) && s[0] == ' ' )
&& !((strcmp(var, "ignoredups") == 0 || strcmp(var, "ignoreboth") ==0) && prev_hist && strcmp(s, prev_hist) == 0)
))
{
free(prev_hist);
prev_hist = strdup(s);
add_history(s);
}
}
#endif
return s;
@ -93,14 +108,14 @@ gets_fromFile(FILE *source)
* The only "flag" right now is 1 for use readline & history.
*/
void
initializeInput(int flags, PsqlSettings *pset)
initializeInput(int flags)
{
#ifdef USE_READLINE
if (flags == 1)
{
useReadline = true;
rl_readline_name = "psql";
initialize_readline(&(pset->db));
initialize_readline(&(pset.db));
}
#endif
@ -110,6 +125,7 @@ initializeInput(int flags, PsqlSettings *pset)
const char *home;
useHistory = true;
SetVariable(pset.vars, "HISTSIZE", "500");
using_history();
home = getenv("HOME");
if (home)
@ -166,6 +182,9 @@ finishInput(void)
psql_history = (char *) malloc(strlen(home) + 20);
if (psql_history)
{
const char * var = GetVariable(pset.vars, "HISTSIZE");
if (var)
stifle_history(atoi(var));
sprintf(psql_history, "%s/.psql_history", home);
write_history(psql_history);
free(psql_history);

View File

@ -42,7 +42,7 @@ char * gets_interactive(const char *prompt);
char * gets_fromFile(FILE *source);
void initializeInput(int flags, PsqlSettings *pset);
void initializeInput(int flags);
bool saveHistory(const char *fname);

View File

@ -1,4 +1,3 @@
#include <config.h>
#include <c.h>
#include "large_obj.h"
@ -33,9 +32,9 @@ _my_notice_handler(void *arg, const char *message)
static bool
handle_transaction(PsqlSettings *pset)
handle_transaction(void)
{
const char *var = GetVariable(pset->vars, "lo_transaction");
const char *var = GetVariable(pset.vars, "LO_TRANSACTION");
PGresult *res;
bool commit;
PQnoticeProcessor old_notice_hook;
@ -46,9 +45,9 @@ handle_transaction(PsqlSettings *pset)
commit = (var && strcmp(var, "commit") == 0);
notice[0] = '\0';
old_notice_hook = PQsetNoticeProcessor(pset->db, _my_notice_handler, NULL);
old_notice_hook = PQsetNoticeProcessor(pset.db, _my_notice_handler, NULL);
res = PSQLexec(pset, commit ? "COMMIT" : "ROLLBACK");
res = PSQLexec(commit ? "COMMIT" : "ROLLBACK");
if (!res)
return false;
@ -58,7 +57,7 @@ handle_transaction(PsqlSettings *pset)
(commit && strcmp(notice, "NOTICE: EndTransactionBlock and not inprogress/abort state\n") != 0))
fputs(notice, stderr);
}
else if (!GetVariableBool(pset->vars, "quiet"))
else if (!QUIET())
{
if (commit)
puts("Warning: Your transaction in progress has been committed.");
@ -66,7 +65,7 @@ handle_transaction(PsqlSettings *pset)
puts("Warning: Your transaction in progress has been rolled back.");
}
PQsetNoticeProcessor(pset->db, old_notice_hook, NULL);
PQsetNoticeProcessor(pset.db, old_notice_hook, NULL);
return true;
}
@ -78,43 +77,43 @@ handle_transaction(PsqlSettings *pset)
* Write a large object to a file
*/
bool
do_lo_export(PsqlSettings *pset, const char *loid_arg, const char *filename_arg)
do_lo_export(const char *loid_arg, const char *filename_arg)
{
PGresult *res;
int status;
bool own_transaction = true;
const char *var = GetVariable(pset->vars, "lo_transaction");
const char *var = GetVariable(pset.vars, "LO_TRANSACTION");
if (var && strcmp(var, "nothing") == 0)
own_transaction = false;
if (!pset->db)
if (!pset.db)
{
if (!pset->cur_cmd_interactive)
fprintf(stderr, "%s: ", pset->progname);
if (!pset.cur_cmd_interactive)
fprintf(stderr, "%s: ", pset.progname);
fputs("\\lo_export: not connected to a database\n", stderr);
return false;
}
if (own_transaction)
{
if (!handle_transaction(pset))
if (!handle_transaction())
return false;
if (!(res = PSQLexec(pset, "BEGIN")))
if (!(res = PSQLexec("BEGIN")))
return false;
PQclear(res);
}
status = lo_export(pset->db, atol(loid_arg), (char *) filename_arg);
status = lo_export(pset.db, atol(loid_arg), (char *) filename_arg);
if (status != 1)
{ /* of course this status is documented
* nowhere :( */
fputs(PQerrorMessage(pset->db), stderr);
fputs(PQerrorMessage(pset.db), stderr);
if (own_transaction)
{
res = PQexec(pset->db, "ROLLBACK");
res = PQexec(pset.db, "ROLLBACK");
PQclear(res);
}
return false;
@ -122,9 +121,9 @@ do_lo_export(PsqlSettings *pset, const char *loid_arg, const char *filename_arg)
if (own_transaction)
{
if (!(res = PSQLexec(pset, "COMMIT")))
if (!(res = PSQLexec("COMMIT")))
{
res = PQexec(pset->db, "ROLLBACK");
res = PQexec(pset.db, "ROLLBACK");
PQclear(res);
return false;
}
@ -132,7 +131,7 @@ do_lo_export(PsqlSettings *pset, const char *loid_arg, const char *filename_arg)
PQclear(res);
}
fprintf(pset->queryFout, "lo_export\n");
fprintf(pset.queryFout, "lo_export\n");
return true;
}
@ -145,44 +144,44 @@ do_lo_export(PsqlSettings *pset, const char *loid_arg, const char *filename_arg)
* Copy large object from file to database
*/
bool
do_lo_import(PsqlSettings *pset, const char *filename_arg, const char *comment_arg)
do_lo_import(const char *filename_arg, const char *comment_arg)
{
PGresult *res;
Oid loid;
char buf[1024];
unsigned int i;
bool own_transaction = true;
const char *var = GetVariable(pset->vars, "lo_transaction");
const char *var = GetVariable(pset.vars, "LO_TRANSACTION");
if (var && strcmp(var, "nothing") == 0)
own_transaction = false;
if (!pset->db)
if (!pset.db)
{
if (!pset->cur_cmd_interactive)
fprintf(stderr, "%s: ", pset->progname);
if (!pset.cur_cmd_interactive)
fprintf(stderr, "%s: ", pset.progname);
fputs("\\lo_import: not connected to a database\n", stderr);
return false;
}
if (own_transaction)
{
if (!handle_transaction(pset))
if (!handle_transaction())
return false;
if (!(res = PSQLexec(pset, "BEGIN")))
if (!(res = PSQLexec("BEGIN")))
return false;
PQclear(res);
}
loid = lo_import(pset->db, (char *) filename_arg);
loid = lo_import(pset.db, (char *) filename_arg);
if (loid == InvalidOid)
{
fputs(PQerrorMessage(pset->db), stderr);
fputs(PQerrorMessage(pset.db), stderr);
if (own_transaction)
{
res = PQexec(pset->db, "ROLLBACK");
res = PQexec(pset.db, "ROLLBACK");
PQclear(res);
}
return false;
@ -199,11 +198,11 @@ do_lo_import(PsqlSettings *pset, const char *filename_arg, const char *comment_a
strncat(buf, &comment_arg[i], 1);
strcat(buf, "')");
if (!(res = PSQLexec(pset, buf)))
if (!(res = PSQLexec(buf)))
{
if (own_transaction)
{
res = PQexec(pset->db, "ROLLBACK");
res = PQexec(pset.db, "ROLLBACK");
PQclear(res);
}
return false;
@ -212,9 +211,9 @@ do_lo_import(PsqlSettings *pset, const char *filename_arg, const char *comment_a
if (own_transaction)
{
if (!(res = PSQLexec(pset, "COMMIT")))
if (!(res = PSQLexec("COMMIT")))
{
res = PQexec(pset->db, "ROLLBACK");
res = PQexec(pset.db, "ROLLBACK");
PQclear(res);
return false;
}
@ -223,8 +222,9 @@ do_lo_import(PsqlSettings *pset, const char *filename_arg, const char *comment_a
}
fprintf(pset->queryFout, "lo_import %d\n", loid);
pset->lastOid = loid;
fprintf(pset.queryFout, "lo_import %d\n", loid);
sprintf(buf, "%u", (unsigned int)loid);
SetVariable(pset.vars, "LASTOID", buf);
return true;
}
@ -237,44 +237,44 @@ do_lo_import(PsqlSettings *pset, const char *filename_arg, const char *comment_a
* removes a large object out of the database
*/
bool
do_lo_unlink(PsqlSettings *pset, const char *loid_arg)
do_lo_unlink(const char *loid_arg)
{
PGresult *res;
int status;
Oid loid = (Oid) atol(loid_arg);
char buf[256];
bool own_transaction = true;
const char *var = GetVariable(pset->vars, "lo_transaction");
const char *var = GetVariable(pset.vars, "LO_TRANSACTION");
if (var && strcmp(var, "nothing") == 0)
own_transaction = false;
if (!pset->db)
if (!pset.db)
{
if (!pset->cur_cmd_interactive)
fprintf(stderr, "%s: ", pset->progname);
if (!pset.cur_cmd_interactive)
fprintf(stderr, "%s: ", pset.progname);
fputs("\\lo_unlink: not connected to a database\n", stderr);
return false;
}
if (own_transaction)
{
if (!handle_transaction(pset))
if (!handle_transaction())
return false;
if (!(res = PSQLexec(pset, "BEGIN")))
if (!(res = PSQLexec("BEGIN")))
return false;
PQclear(res);
}
status = lo_unlink(pset->db, loid);
status = lo_unlink(pset.db, loid);
if (status == -1)
{
fputs(PQerrorMessage(pset->db), stderr);
fputs(PQerrorMessage(pset.db), stderr);
if (own_transaction)
{
res = PQexec(pset->db, "ROLLBACK");
res = PQexec(pset.db, "ROLLBACK");
PQclear(res);
}
return false;
@ -282,11 +282,11 @@ do_lo_unlink(PsqlSettings *pset, const char *loid_arg)
/* remove the comment as well */
sprintf(buf, "DELETE FROM pg_description WHERE objoid = %d", loid);
if (!(res = PSQLexec(pset, buf)))
if (!(res = PSQLexec(buf)))
{
if (own_transaction)
{
res = PQexec(pset->db, "ROLLBACK");
res = PQexec(pset.db, "ROLLBACK");
PQclear(res);
}
return false;
@ -295,9 +295,9 @@ do_lo_unlink(PsqlSettings *pset, const char *loid_arg)
if (own_transaction)
{
if (!(res = PSQLexec(pset, "COMMIT")))
if (!(res = PSQLexec("COMMIT")))
{
res = PQexec(pset->db, "ROLLBACK");
res = PQexec(pset.db, "ROLLBACK");
PQclear(res);
return false;
}
@ -305,7 +305,7 @@ do_lo_unlink(PsqlSettings *pset, const char *loid_arg)
}
fprintf(pset->queryFout, "lo_unlink %d\n", loid);
fprintf(pset.queryFout, "lo_unlink %d\n", loid);
return true;
}
@ -318,11 +318,11 @@ do_lo_unlink(PsqlSettings *pset, const char *loid_arg)
* Show all large objects in database with comments
*/
bool
do_lo_list(PsqlSettings *pset)
do_lo_list(void)
{
PGresult *res;
char buf[1024];
printQueryOpt myopt = pset->popt;
printQueryOpt myopt = pset.popt;
strcpy(buf,
"SELECT usename as \"Owner\", substring(relname from 5) as \"ID\",\n"
@ -336,7 +336,7 @@ do_lo_list(PsqlSettings *pset)
"WHERE not exists (select 1 from pg_user where usesysid = relowner) AND relkind = 'l'\n"
"ORDER BY \"ID\"");
res = PSQLexec(pset, buf);
res = PSQLexec(buf);
if (!res)
return false;
@ -344,7 +344,7 @@ do_lo_list(PsqlSettings *pset)
myopt.nullPrint = NULL;
myopt.title = "Large objects";
printQuery(res, &myopt, pset->queryFout);
printQuery(res, &myopt, pset.queryFout);
PQclear(res);
return true;

View File

@ -2,11 +2,10 @@
#define LARGE_OBJ_H
#include <c.h>
#include "settings.h"
bool do_lo_export(PsqlSettings *pset, const char *loid_arg, const char *filename_arg);
bool do_lo_import(PsqlSettings *pset, const char *filename_arg, const char *comment_arg);
bool do_lo_unlink(PsqlSettings *pset, const char *loid_arg);
bool do_lo_list(PsqlSettings *pset);
bool do_lo_export(const char *loid_arg, const char *filename_arg);
bool do_lo_import(const char *filename_arg, const char *comment_arg);
bool do_lo_unlink(const char *loid_arg);
bool do_lo_list(void);
#endif /* LARGE_OBJ_H */

View File

@ -1,4 +1,3 @@
#include <config.h>
#include <c.h>
#include "mainloop.h"
@ -26,7 +25,7 @@
* FIXME: rewrite this whole thing with flex
*/
int
MainLoop(PsqlSettings *pset, FILE *source)
MainLoop(FILE *source)
{
PQExpBuffer query_buf; /* buffer for query being accumulated */
PQExpBuffer previous_buf; /* if there isn't anything in the new buffer
@ -36,13 +35,14 @@ MainLoop(PsqlSettings *pset, FILE *source)
int successResult = EXIT_SUCCESS;
backslashResult slashCmdStatus;
bool eof = false; /* end of our command input? */
bool success;
char in_quote; /* == 0 for no in_quote */
bool was_bslash; /* backslash */
bool xcomment; /* in extended comment */
int paren_level;
unsigned int query_start;
int count_eof;
const char *var;
int i,
prevlen,
@ -56,12 +56,12 @@ MainLoop(PsqlSettings *pset, FILE *source)
/* Save old settings */
prev_cmd_source = pset->cur_cmd_source;
prev_cmd_interactive = pset->cur_cmd_interactive;
prev_cmd_source = pset.cur_cmd_source;
prev_cmd_interactive = pset.cur_cmd_interactive;
/* Establish new source */
pset->cur_cmd_source = source;
pset->cur_cmd_interactive = ((source == stdin) && !pset->notty);
pset.cur_cmd_source = source;
pset.cur_cmd_interactive = ((source == stdin) && !pset.notty);
query_buf = createPQExpBuffer();
@ -79,7 +79,7 @@ MainLoop(PsqlSettings *pset, FILE *source)
/* main loop to get queries and execute them */
while (!eof)
while (1)
{
if (slashCmdStatus == CMD_NEWEDIT)
{
@ -102,7 +102,7 @@ MainLoop(PsqlSettings *pset, FILE *source)
* otherwise, set interactive prompt if necessary and get
* another line
*/
if (pset->cur_cmd_interactive)
if (pset.cur_cmd_interactive)
{
int prompt_status;
@ -117,7 +117,7 @@ MainLoop(PsqlSettings *pset, FILE *source)
else
prompt_status = PROMPT_READY;
line = gets_interactive(get_prompt(pset, prompt_status));
line = gets_interactive(get_prompt(prompt_status));
}
else
line = gets_fromFile(source);
@ -125,7 +125,7 @@ MainLoop(PsqlSettings *pset, FILE *source)
/* Setting this will not have effect until next line. */
die_on_error = GetVariableBool(pset->vars, "die_on_error");
die_on_error = GetVariableBool(pset.vars, "EXIT_ON_ERROR");
/*
* query_buf holds query already accumulated. line is the
@ -137,14 +137,47 @@ MainLoop(PsqlSettings *pset, FILE *source)
/* No more input. Time to quit, or \i done */
if (line == NULL)
{
if (GetVariableBool(pset->vars, "echo") && !GetVariableBool(pset->vars, "quiet"))
puts("EOF");
else if (pset->cur_cmd_interactive)
putc('\n', stdout); /* just newline */
if (pset.cur_cmd_interactive)
{
bool getout = true;
eof = true;
continue;
/* 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 */
}
if (getout)
{
putc('\n', stdout); /* just newline */
break;
}
else
{
if (!QUIET())
printf("Use \"\\q\" to leave %s.\n", pset.progname);
continue;
}
}
else /* not interactive */
break;
}
else
count_eof = 0;
/* strip trailing backslashes, they don't have a clear meaning */
while (1)
@ -164,11 +197,11 @@ MainLoop(PsqlSettings *pset, FILE *source)
continue;
}
/* echo back if input is from file and flag is set */
if (!pset->cur_cmd_interactive && GetVariableBool(pset->vars, "echo"))
puts(line);
/* echo back if flag is set */
var = GetVariable(pset.vars, "ECHO");
if (var && strcmp(var, "full")==0)
puts(line);
fflush(stdout);
len = strlen(line);
query_start = 0;
@ -236,8 +269,7 @@ MainLoop(PsqlSettings *pset, FILE *source)
/* colon -> substitute variable */
/* we need to be on the watch for the '::' operator */
else if (line[i] == ':' && !was_bslash &&
strspn(line+i+thislen, VALID_VARIABLE_CHARS)>0 &&
(prevlen > 0 && line[i-prevlen]!=':')
strspn(line+i+thislen, VALID_VARIABLE_CHARS)>0
)
{
size_t in_length,
@ -250,24 +282,35 @@ MainLoop(PsqlSettings *pset, FILE *source)
in_length = strspn(&line[i + thislen], VALID_VARIABLE_CHARS);
after = line[i + thislen + in_length];
line[i + thislen + in_length] = '\0';
value = interpolate_var(&line[i + thislen], pset);
out_length = strlen(value);
new = malloc(len + out_length - (1 + in_length) + 1);
if (!new)
{
perror("malloc");
exit(EXIT_FAILURE);
}
/* if the variable doesn't exist we'll leave the string as is */
value = GetVariable(pset.vars, &line[i + thislen]);
if (value)
{
out_length = strlen(value);
sprintf(new, "%.*s%s%c", i, line, value, after);
if (after)
strcat(new, line + i + 1 + in_length + 1);
new = malloc(len + out_length - (1 + in_length) + 1);
if (!new)
{
perror("malloc");
exit(EXIT_FAILURE);
}
free(line);
line = new;
len = strlen(new);
continue; /* reparse the just substituted */
sprintf(new, "%.*s%s%c", i, line, value, after);
if (after)
strcat(new, line + i + 1 + in_length + 1);
free(line);
line = new;
len = strlen(new);
continue; /* reparse the just substituted */
}
else
{
/* restore overwritten character */
line[i + thislen + in_length] = after;
/* move on ... */
}
}
/* semicolon? then send query */
@ -288,7 +331,7 @@ MainLoop(PsqlSettings *pset, FILE *source)
}
/* execute query */
success = SendQuery(pset, query_buf->data);
success = SendQuery(query_buf->data);
slashCmdStatus = success ? CMD_SEND : CMD_ERROR;
resetPQExpBuffer(previous_buf);
@ -314,7 +357,7 @@ MainLoop(PsqlSettings *pset, FILE *source)
paren_level = 0;
line[i - prevlen] = '\0'; /* overwrites backslash */
/* is there anything else on the line? */
/* is there anything else on the line for the command? */
if (line[query_start + strspn(line + query_start, " \t")] != '\0')
{
/*
@ -328,7 +371,7 @@ MainLoop(PsqlSettings *pset, FILE *source)
}
/* handle backslash command */
slashCmdStatus = HandleSlashCmds(pset, &line[i],
slashCmdStatus = HandleSlashCmds(&line[i],
query_buf->len>0 ? query_buf : previous_buf,
&end_of_cmd);
@ -342,7 +385,7 @@ MainLoop(PsqlSettings *pset, FILE *source)
if (slashCmdStatus == CMD_SEND)
{
success = SendQuery(pset, query_buf->data);
success = SendQuery(query_buf->data);
query_start = i + thislen;
resetPQExpBuffer(previous_buf);
@ -350,14 +393,9 @@ MainLoop(PsqlSettings *pset, FILE *source)
resetPQExpBuffer(query_buf);
}
/* is there anything left after the backslash command? */
if (end_of_cmd)
{
i += end_of_cmd - &line[i];
query_start = i;
}
else
break;
/* process anything left after the backslash command */
i += end_of_cmd - &line[i];
query_start = i;
}
@ -387,9 +425,9 @@ MainLoop(PsqlSettings *pset, FILE *source)
/* In single line mode, send off the query if any */
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(query_buf->data);
slashCmdStatus = success ? CMD_SEND : CMD_ERROR;
resetPQExpBuffer(previous_buf);
appendPQExpBufferStr(previous_buf, query_buf->data);
@ -397,7 +435,7 @@ MainLoop(PsqlSettings *pset, FILE *source)
}
if (!success && die_on_error && !pset->cur_cmd_interactive)
if (!success && die_on_error && !pset.cur_cmd_interactive)
{
successResult = EXIT_USER;
break;
@ -405,18 +443,18 @@ MainLoop(PsqlSettings *pset, FILE *source)
/* 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;
break;
}
} /* while !EOF */
} /* while !endofprogram */
destroyPQExpBuffer(query_buf);
destroyPQExpBuffer(previous_buf);
pset->cur_cmd_source = prev_cmd_source;
pset->cur_cmd_interactive = prev_cmd_interactive;
pset.cur_cmd_source = prev_cmd_source;
pset.cur_cmd_interactive = prev_cmd_interactive;
return successResult;
} /* MainLoop() */

View File

@ -2,9 +2,7 @@
#define MAINLOOP_H
#include <stdio.h>
#include "settings.h"
int
MainLoop(PsqlSettings *pset, FILE *source);
int MainLoop(FILE *source);
#endif /* MAINLOOP_H */

View File

@ -1,4 +1,3 @@
#include <config.h>
#include <c.h>
#include "prompt.h"
@ -10,6 +9,7 @@
#include "settings.h"
#include "common.h"
#include "variables.h"
#ifdef WIN32
#define popen(x,y) _popen(x,y)
@ -22,7 +22,7 @@
* get_prompt
*
* Returns a statically allocated prompt made by interpolating certain
* tcsh style escape sequences into pset->vars "prompt1|2|3".
* tcsh style escape sequences into pset->vars "PROMPT1|2|3".
* (might not be completely multibyte safe)
*
* Defined interpolations are:
@ -46,8 +46,7 @@
*
* %`command` - The result of executing command in /bin/sh with trailing
* newline stripped.
* %$name$ - The value of the psql/environment/magic varible 'name'
* (same rules as for, e.g., \echo $foo)
* %$name$ - The value of the psql variable 'name'
* (those will not be rescanned for more escape sequences!)
*
*
@ -56,7 +55,7 @@
*--------------------------
*/
const char *
get_prompt(PsqlSettings *pset, promptStatus_t status)
get_prompt(promptStatus_t status)
{
#define MAX_PROMPT_SIZE 256
static char destination[MAX_PROMPT_SIZE + 1];
@ -66,11 +65,11 @@ get_prompt(PsqlSettings *pset, promptStatus_t status)
const char *prompt_string;
if (status == PROMPT_READY)
prompt_string = GetVariable(pset->vars, "prompt1");
prompt_string = GetVariable(pset.vars, "PROMPT1");
else if (status == PROMPT_CONTINUE || status == PROMPT_SINGLEQUOTE || status == PROMPT_DOUBLEQUOTE || status == PROMPT_COMMENT)
prompt_string = GetVariable(pset->vars, "prompt2");
prompt_string = GetVariable(pset.vars, "PROMPT2");
else if (status == PROMPT_COPY)
prompt_string = GetVariable(pset->vars, "prompt3");
prompt_string = GetVariable(pset.vars, "PROMPT3");
else
prompt_string = "? ";
@ -92,31 +91,31 @@ get_prompt(PsqlSettings *pset, promptStatus_t status)
/* Current database */
case '/':
if (pset->db)
strncpy(buf, PQdb(pset->db), MAX_PROMPT_SIZE);
if (pset.db)
strncpy(buf, PQdb(pset.db), MAX_PROMPT_SIZE);
break;
case '~':
{
const char *var;
if (pset->db)
if (pset.db)
{
if (strcmp(PQdb(pset->db), PQuser(pset->db)) == 0 ||
((var = getenv("PGDATABASE")) && strcmp(var, PQdb(pset->db)) == 0))
if (strcmp(PQdb(pset.db), PQuser(pset.db)) == 0 ||
((var = getenv("PGDATABASE")) && strcmp(var, PQdb(pset.db)) == 0))
strcpy(buf, "~");
else
strncpy(buf, PQdb(pset->db), MAX_PROMPT_SIZE);
strncpy(buf, PQdb(pset.db), MAX_PROMPT_SIZE);
}
break;
}
/* DB server hostname (long/short) */
case 'M':
case 'm':
if (pset->db)
if (pset.db)
{
if (PQhost(pset->db))
if (PQhost(pset.db))
{
strncpy(buf, PQhost(pset->db), MAX_PROMPT_SIZE);
strncpy(buf, PQhost(pset.db), MAX_PROMPT_SIZE);
if (*p == 'm')
buf[strcspn(buf, ".")] = '\0';
}
@ -126,13 +125,13 @@ get_prompt(PsqlSettings *pset, promptStatus_t status)
break;
/* DB server port number */
case '>':
if (pset->db && PQport(pset->db))
strncpy(buf, PQport(pset->db), MAX_PROMPT_SIZE);
if (pset.db && PQport(pset.db))
strncpy(buf, PQport(pset.db), MAX_PROMPT_SIZE);
break;
/* DB server user name */
case 'n':
if (pset->db)
strncpy(buf, PQuser(pset->db), MAX_PROMPT_SIZE);
if (pset.db)
strncpy(buf, PQuser(pset.db), MAX_PROMPT_SIZE);
break;
case '0':
@ -159,9 +158,9 @@ get_prompt(PsqlSettings *pset, promptStatus_t status)
switch (status)
{
case PROMPT_READY:
if (!pset->db)
if (!pset.db)
buf[0] = '!';
else if (!GetVariableBool(pset->vars, "singleline"))
else if (!GetVariableBool(pset.vars, "SINGLELINE"))
buf[0] = '=';
else
buf[0] = '^';
@ -189,7 +188,7 @@ get_prompt(PsqlSettings *pset, promptStatus_t status)
case '#':
{
if (pset->db && strcmp(PQuser(pset->db), "postgres") == 0)
if (pset.db && strcmp(PQuser(pset.db), "postgres") == 0)
buf[0] = '#';
else
buf[0] = '>';
@ -230,7 +229,7 @@ get_prompt(PsqlSettings *pset, promptStatus_t status)
name = strdup(p + 1);
nameend = strcspn(name, "$");
name[nameend] = '\0';
val = interpolate_var(name, pset);
val = GetVariable(pset.vars, name);
if (val)
strncpy(buf, val, MAX_PROMPT_SIZE);
free(name);

View File

@ -14,7 +14,7 @@ typedef enum _promptStatus
} promptStatus_t;
const char *
get_prompt(PsqlSettings *pset, promptStatus_t status);
get_prompt(promptStatus_t status);
#endif /* PROMPT_H */

View File

@ -43,11 +43,13 @@ typedef struct _psqlSettings
bool has_client_encoding; /* was PGCLIENTENCODING set on
* startup? */
Oid lastOid; /* saves oid from insert command
because people want it so badly */
char *progname; /* in case you renamed psql */
} PsqlSettings;
extern PsqlSettings pset;
#define QUIET() (GetVariableBool(pset.vars, "QUIET"))
#ifndef EXIT_SUCCESS

View File

@ -1,4 +1,3 @@
#include <config.h>
#include <c.h>
#include <signal.h>
@ -34,10 +33,10 @@
#include "print.h"
#include "describe.h"
PsqlSettings pset;
static void
process_psqlrc(PsqlSettings *pset);
process_psqlrc(void);
static void
showVersion(void);
@ -67,7 +66,7 @@ struct adhoc_opts
};
static void
parse_options(int argc, char *argv[], PsqlSettings *pset, struct adhoc_opts * options);
parse_options(int argc, char *argv[], struct adhoc_opts * options);
@ -79,7 +78,6 @@ parse_options(int argc, char *argv[], PsqlSettings *pset, struct adhoc_opts * op
int
main(int argc, char **argv)
{
PsqlSettings settings;
struct adhoc_opts options;
int successResult;
@ -87,64 +85,65 @@ main(int argc, char **argv)
char *password = NULL;
bool need_pass;
memset(&settings, 0, sizeof settings);
memset(&pset, 0, sizeof pset);
if (!strrchr(argv[0], SEP_CHAR))
settings.progname = argv[0];
pset.progname = argv[0];
else
settings.progname = strrchr(argv[0], SEP_CHAR) + 1;
pset.progname = strrchr(argv[0], SEP_CHAR) + 1;
settings.cur_cmd_source = stdin;
settings.cur_cmd_interactive = false;
pset.cur_cmd_source = stdin;
pset.cur_cmd_interactive = false;
settings.vars = CreateVariableSpace();
settings.popt.topt.format = PRINT_ALIGNED;
settings.queryFout = stdout;
settings.popt.topt.fieldSep = strdup(DEFAULT_FIELD_SEP);
settings.popt.topt.border = 1;
settings.popt.topt.pager = 1;
pset.vars = CreateVariableSpace();
pset.popt.topt.format = PRINT_ALIGNED;
pset.queryFout = stdout;
pset.popt.topt.fieldSep = strdup(DEFAULT_FIELD_SEP);
pset.popt.topt.border = 1;
pset.popt.topt.pager = 1;
SetVariable(settings.vars, "prompt1", DEFAULT_PROMPT1);
SetVariable(settings.vars, "prompt2", DEFAULT_PROMPT2);
SetVariable(settings.vars, "prompt3", DEFAULT_PROMPT3);
SetVariable(pset.vars, "PROMPT1", DEFAULT_PROMPT1);
SetVariable(pset.vars, "PROMPT2", DEFAULT_PROMPT2);
SetVariable(pset.vars, "PROMPT3", DEFAULT_PROMPT3);
SetVariable(pset.vars, "VERSION", PG_VERSION_STR);
settings.notty = (!isatty(fileno(stdin)) || !isatty(fileno(stdout)));
pset.notty = (!isatty(fileno(stdin)) || !isatty(fileno(stdout)));
/* This is obsolete and will be removed very soon. */
#ifdef PSQL_ALWAYS_GET_PASSWORDS
settings.getPassword = true;
pset.getPassword = true;
#else
settings.getPassword = false;
pset.getPassword = false;
#endif
#ifdef MULTIBYTE
settings.has_client_encoding = (getenv("PGCLIENTENCODING") != NULL);
pset.has_client_encoding = (getenv("PGCLIENTENCODING") != NULL);
#endif
parse_options(argc, argv, &settings, &options);
parse_options(argc, argv, &options);
if (options.action == ACT_LIST_DB)
options.dbname = "template1";
if (options.username)
{
if (strcmp(options.username, "?") == 0)
if (strcmp(options.username, "\001") == 0)
username = simple_prompt("Username: ", 100, true);
else
username = strdup(options.username);
}
if (settings.getPassword)
if (pset.getPassword)
password = simple_prompt("Password: ", 100, false);
/* loop until we have a password if requested by backend */
do
{
need_pass = false;
settings.db = PQsetdbLogin(options.host, options.port, NULL, NULL, options.dbname, username, password);
pset.db = PQsetdbLogin(options.host, options.port, NULL, NULL, options.dbname, username, password);
if (PQstatus(settings.db) == CONNECTION_BAD &&
strcmp(PQerrorMessage(settings.db), "fe_sendauth: no password supplied\n") == 0)
if (PQstatus(pset.db) == CONNECTION_BAD &&
strcmp(PQerrorMessage(pset.db), "fe_sendauth: no password supplied\n") == 0)
{
need_pass = true;
free(password);
@ -156,58 +155,61 @@ main(int argc, char **argv)
free(username);
free(password);
if (PQstatus(settings.db) == CONNECTION_BAD)
if (PQstatus(pset.db) == CONNECTION_BAD)
{
fprintf(stderr, "%s: connection to database '%s' failed.\n%s",
settings.progname, PQdb(settings.db),
PQerrorMessage(settings.db));
PQfinish(settings.db);
fprintf(stderr, "%s: connection to database '%s' failed - %s",
pset.progname, PQdb(pset.db), PQerrorMessage(pset.db));
PQfinish(pset.db);
exit(EXIT_BADCONN);
}
if (options.action == ACT_LIST_DB)
{
int success = listAllDbs(&settings, false);
int success = listAllDbs(false);
PQfinish(settings.db);
PQfinish(pset.db);
exit(!success);
}
SetVariable(pset.vars, "DBNAME", PQdb(pset.db));
SetVariable(pset.vars, "USER", PQuser(pset.db));
SetVariable(pset.vars, "HOST", PQhost(pset.db));
SetVariable(pset.vars, "PORT", PQport(pset.db));
if (!GetVariable(settings.vars, "quiet") && !settings.notty && !options.action)
if (!QUIET() && !pset.notty && !options.action)
{
printf("Welcome to %s, the PostgreSQL interactive terminal.\n\n"
"Type: \\copyright for distribution terms\n"
" \\h for help with SQL commands\n"
" \\? for help on internal slash commands\n"
" \\g or terminate with semicolon to execute query\n"
" \\q to quit\n", settings.progname);
" \\q to quit\n", pset.progname);
}
process_psqlrc(&settings);
initializeInput(options.no_readline ? 0 : 1, &settings);
/* Now find something to do */
/* process file given by -f */
if (options.action == ACT_FILE)
successResult = process_file(options.action_string, &settings) ? 0 : 1;
successResult = process_file(options.action_string) ? 0 : 1;
/* process slash command if one was given to -c */
else if (options.action == ACT_SINGLE_SLASH)
successResult = HandleSlashCmds(&settings, options.action_string, NULL, NULL) != CMD_ERROR ? 0 : 1;
successResult = HandleSlashCmds(options.action_string, NULL, NULL) != CMD_ERROR ? 0 : 1;
/* If the query given to -c was a normal one, send it */
else if (options.action == ACT_SINGLE_QUERY)
successResult = SendQuery(&settings, options.action_string) ? 0 : 1;
successResult = SendQuery( options.action_string) ? 0 : 1;
/* or otherwise enter interactive main loop */
else
successResult = MainLoop(&settings, stdin);
{
process_psqlrc();
initializeInput(options.no_readline ? 0 : 1);
successResult = MainLoop(stdin);
finishInput();
}
/* clean up */
finishInput();
PQfinish(settings.db);
setQFout(NULL, &settings);
DestroyVariableSpace(settings.vars);
PQfinish(pset.db);
setQFout(NULL);
DestroyVariableSpace(pset.vars);
return successResult;
}
@ -225,7 +227,7 @@ int getopt(int, char *const[], const char *);
#endif
static void
parse_options(int argc, char *argv[], PsqlSettings *pset, struct adhoc_opts * options)
parse_options(int argc, char *argv[], struct adhoc_opts * options)
{
#ifdef HAVE_GETOPT_LONG
static struct option long_options[] = {
@ -234,9 +236,7 @@ parse_options(int argc, char *argv[], PsqlSettings *pset, struct adhoc_opts * op
{"database", required_argument, NULL, 'd'},
{"dbname", required_argument, NULL, 'd'},
{"echo", no_argument, NULL, 'e'},
{"echo-queries", no_argument, NULL, 'e'},
{"echo-all", no_argument, NULL, 'E'},
{"echo-all-queries", no_argument, NULL, 'E'},
{"echo-hidden", no_argument, NULL, 'E'},
{"file", required_argument, NULL, 'f'},
{"field-separator", required_argument, NULL, 'F'},
{"host", required_argument, NULL, 'h'},
@ -261,12 +261,12 @@ parse_options(int argc, char *argv[], PsqlSettings *pset, struct adhoc_opts * op
};
int optindex;
#endif
extern char *optarg;
extern int optind;
int c;
bool used_old_u_option = false;
memset(options, 0, sizeof *options);
@ -284,7 +284,7 @@ parse_options(int argc, char *argv[], PsqlSettings *pset, struct adhoc_opts * op
switch (c)
{
case 'A':
pset->popt.topt.format = PRINT_UNALIGNED;
pset.popt.topt.format = PRINT_UNALIGNED;
break;
case 'c':
options->action_string = optarg;
@ -297,23 +297,23 @@ parse_options(int argc, char *argv[], PsqlSettings *pset, struct adhoc_opts * op
options->dbname = optarg;
break;
case 'e':
SetVariable(pset->vars, "echo", "");
SetVariable(pset.vars, "ECHO", "full");
break;
case 'E':
SetVariable(pset->vars, "echo_secret", "");
SetVariable(pset.vars, "ECHO_HIDDEN", "");
break;
case 'f':
options->action = ACT_FILE;
options->action_string = optarg;
break;
case 'F':
pset->popt.topt.fieldSep = strdup(optarg);
pset.popt.topt.fieldSep = strdup(optarg);
break;
case 'h':
options->host = optarg;
break;
case 'H':
pset->popt.topt.format = PRINT_HTML;
pset.popt.topt.format = PRINT_HTML;
break;
case 'l':
options->action = ACT_LIST_DB;
@ -322,7 +322,7 @@ parse_options(int argc, char *argv[], PsqlSettings *pset, struct adhoc_opts * op
options->no_readline = true;
break;
case 'o':
setQFout(optarg, pset);
setQFout(optarg);
break;
case 'p':
options->port = optarg;
@ -336,16 +336,16 @@ parse_options(int argc, char *argv[], PsqlSettings *pset, struct adhoc_opts * op
value = xstrdup(optarg);
equal_loc = strchr(value, '=');
if (!equal_loc)
result = do_pset(value, NULL, &pset->popt, true);
result = do_pset(value, NULL, &pset.popt, true);
else
{
*equal_loc = '\0';
result = do_pset(value, equal_loc + 1, &pset->popt, true);
result = do_pset(value, equal_loc + 1, &pset.popt, true);
}
if (!result)
{
fprintf(stderr, "Couldn't set printing paramter %s.\n", value);
fprintf(stderr, "%s: couldn't set printing parameter %s\n", pset.progname, value);
exit(EXIT_FAILURE);
}
@ -353,29 +353,31 @@ parse_options(int argc, char *argv[], PsqlSettings *pset, struct adhoc_opts * op
break;
}
case 'q':
SetVariable(pset->vars, "quiet", "");
SetVariable(pset.vars, "QUIET", "");
break;
case 's':
SetVariable(pset->vars, "singlestep", "");
SetVariable(pset.vars, "SINGLESTEP", "");
break;
case 'S':
SetVariable(pset->vars, "singleline", "");
SetVariable(pset.vars, "SINGLELINE", "");
break;
case 't':
pset->popt.topt.tuples_only = true;
pset.popt.topt.tuples_only = true;
break;
case 'T':
pset->popt.topt.tableAttr = xstrdup(optarg);
pset.popt.topt.tableAttr = xstrdup(optarg);
break;
case 'u':
pset->getPassword = true;
options->username = "?";
pset.getPassword = true;
options->username = "\001"; /* hopefully nobody has that username */
/* this option is out */
used_old_u_option = true;
break;
case 'U':
options->username = optarg;
break;
case 'x':
pset->popt.topt.expanded = true;
pset.popt.topt.expanded = true;
break;
case 'v':
{
@ -386,20 +388,20 @@ parse_options(int argc, char *argv[], PsqlSettings *pset, struct adhoc_opts * op
equal_loc = strchr(value, '=');
if (!equal_loc)
{
if (!DeleteVariable(pset->vars, value))
if (!DeleteVariable(pset.vars, value))
{
fprintf(stderr, "%s: could not delete variable %s\n",
pset->progname, value);
pset.progname, value);
exit(EXIT_FAILURE);
}
}
else
{
*equal_loc = '\0';
if (!SetVariable(pset->vars, value, equal_loc + 1))
if (!SetVariable(pset.vars, value, equal_loc + 1))
{
fprintf(stderr, "%s: Couldn't set variable %s to %s\n",
pset->progname, value, equal_loc);
fprintf(stderr, "%s: could not set variable %s\n",
pset.progname, value);
exit(EXIT_FAILURE);
}
}
@ -411,7 +413,7 @@ parse_options(int argc, char *argv[], PsqlSettings *pset, struct adhoc_opts * op
showVersion();
exit(EXIT_SUCCESS);
case 'W':
pset->getPassword = true;
pset.getPassword = true;
break;
case '?':
usage();
@ -420,7 +422,7 @@ parse_options(int argc, char *argv[], PsqlSettings *pset, struct adhoc_opts * op
#ifndef HAVE_GETOPT_LONG
case '-':
fprintf(stderr, "%s was compiled without support for long options.\n"
"Use -? for help on invocation options.\n", pset->progname);
"Use -? for help on invocation options.\n", pset.progname);
exit(EXIT_FAILURE);
break;
#endif
@ -441,12 +443,16 @@ parse_options(int argc, char *argv[], PsqlSettings *pset, struct adhoc_opts * op
options->dbname = argv[optind];
else if (!options->username)
options->username = argv[optind];
else
else if (!QUIET())
fprintf(stderr, "%s: warning: extra option %s ignored\n",
pset->progname, argv[optind]);
pset.progname, argv[optind]);
optind++;
}
if (used_old_u_option && !QUIET())
fprintf(stderr, "%s: Warning: The -u option is deprecated. Use -U.\n", pset.progname);
}
@ -455,7 +461,7 @@ parse_options(int argc, char *argv[], PsqlSettings *pset, struct adhoc_opts * op
* Load /etc/psqlrc or .psqlrc file, if found.
*/
static void
process_psqlrc(PsqlSettings *pset)
process_psqlrc(void)
{
char *psqlrc;
char *home;
@ -466,9 +472,9 @@ process_psqlrc(PsqlSettings *pset)
/* System-wide startup file */
if (access("/etc/psqlrc-" PG_RELEASE "." PG_VERSION "." PG_SUBVERSION, R_OK) == 0)
process_file("/etc/psqlrc-" PG_RELEASE "." PG_VERSION "." PG_SUBVERSION, pset);
process_file("/etc/psqlrc-" PG_RELEASE "." PG_VERSION "." PG_SUBVERSION);
else if (access("/etc/psqlrc", R_OK) == 0)
process_file("/etc/psqlrc", pset);
process_file("/etc/psqlrc");
/* Look for one in the home dir */
home = getenv("HOME");
@ -484,12 +490,12 @@ process_psqlrc(PsqlSettings *pset)
sprintf(psqlrc, "%s/.psqlrc-" PG_RELEASE "." PG_VERSION "." PG_SUBVERSION, home);
if (access(psqlrc, R_OK) == 0)
process_file(psqlrc, pset);
process_file(psqlrc);
else
{
sprintf(psqlrc, "%s/.psqlrc", home);
if (access(psqlrc, R_OK) == 0)
process_file(psqlrc, pset);
process_file(psqlrc);
}
free(psqlrc);
}
@ -529,7 +535,7 @@ showVersion(void)
#else
#define _Feature
#endif
fputs("multibyte");
fputs("multibyte", stdout);
#endif
#undef _Feature