aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPeter Eisentraut <peter_e@gmx.net>2000-01-14 22:18:03 +0000
committerPeter Eisentraut <peter_e@gmx.net>2000-01-14 22:18:03 +0000
commit7c9390caa14ea2d5d99d69d2a34eee4d45d43b9c (patch)
tree7fdf1a26847ab31eee6ab32fc4d77138040971cf /src
parent4ceb2d0cb619bba2ecbf5d72a10c8fa7ba321366 (diff)
downloadpostgresql-7c9390caa14ea2d5d99d69d2a34eee4d45d43b9c.tar.gz
postgresql-7c9390caa14ea2d5d99d69d2a34eee4d45d43b9c.zip
Fixed psql variables vs array syntax, as well as minor psql enhancements
Diffstat (limited to 'src')
-rw-r--r--src/bin/psql/command.c272
-rw-r--r--src/bin/psql/command.h13
-rw-r--r--src/bin/psql/common.c312
-rw-r--r--src/bin/psql/common.h9
-rw-r--r--src/bin/psql/copy.c85
-rw-r--r--src/bin/psql/copy.h2
-rw-r--r--src/bin/psql/describe.c102
-rw-r--r--src/bin/psql/describe.h18
-rw-r--r--src/bin/psql/help.c15
-rw-r--r--src/bin/psql/help.h2
-rw-r--r--src/bin/psql/input.c27
-rw-r--r--src/bin/psql/input.h2
-rw-r--r--src/bin/psql/large_obj.c110
-rw-r--r--src/bin/psql/large_obj.h9
-rw-r--r--src/bin/psql/mainloop.c158
-rw-r--r--src/bin/psql/mainloop.h4
-rw-r--r--src/bin/psql/prompt.c49
-rw-r--r--src/bin/psql/prompt.h2
-rw-r--r--src/bin/psql/settings.h6
-rw-r--r--src/bin/psql/startup.c180
20 files changed, 693 insertions, 684 deletions
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index ba016120590..d658df1e572 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -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);
}
diff --git a/src/bin/psql/command.h b/src/bin/psql/command.h
index 029937e3371..a8cc220e7c9 100644
--- a/src/bin/psql/command.h
+++ b/src/bin/psql/command.h
@@ -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
diff --git a/src/bin/psql/common.c b/src/bin/psql/common.c
index 584a8bf1c26..8133faa467a 100644
--- a/src/bin/psql/common.c
+++ b/src/bin/psql/common.c
@@ -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);
@@ -212,93 +193,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
*
* Before we start a query, we enable a SIGINT signal catcher that sends a
@@ -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);
- PQclear(res);
- return NULL;
+ 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);
}
- /* 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)
+ 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("Failed.\n", stderr);
- PQfinish(pset->db);
- pset->db = NULL;
+ fputs(PQerrorMessage(pset.db), stderr);
+ PQclear(res);
+ return 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:
+ {
+ char buf[10];
+
success = true;
- pset->lastOid = PQoidValue(results);
- if (!GetVariableBool(pset->vars, "quiet"))
- fprintf(pset->queryFout, "%s\n", PQcmdStatus(results));
+ 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;
}
diff --git a/src/bin/psql/common.h b/src/bin/psql/common.h
index e3924e9d92d..7d285d01ccd 100644
--- a/src/bin/psql/common.h
+++ b/src/bin/psql/common.h
@@ -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 */
diff --git a/src/bin/psql/copy.c b/src/bin/psql/copy.c
index 800a8f41eda..66449873346 100644
--- a/src/bin/psql/copy.c
+++ b/src/bin/psql/copy.c
@@ -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);
diff --git a/src/bin/psql/copy.h b/src/bin/psql/copy.h
index 6e01c5457d1..840fb27fe12 100644
--- a/src/bin/psql/copy.h
+++ b/src/bin/psql/copy.h
@@ -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 */
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index f4ac7f1bcd3..1d544837546 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -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);
diff --git a/src/bin/psql/describe.h b/src/bin/psql/describe.h
index 960942f52ff..834375b252f 100644
--- a/src/bin/psql/describe.h
+++ b/src/bin/psql/describe.h
@@ -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 */
diff --git a/src/bin/psql/help.c b/src/bin/psql/help.c
index c108743deb2..47fc0d8fc51 100644
--- a/src/bin/psql/help.c
+++ b/src/bin/psql/help.c
@@ -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");
diff --git a/src/bin/psql/help.h b/src/bin/psql/help.h
index 791e0313ca1..db709268568 100644
--- a/src/bin/psql/help.h
+++ b/src/bin/psql/help.h
@@ -5,7 +5,7 @@
void usage(void);
-void slashUsage(PsqlSettings *pset);
+void slashUsage(void);
void helpSQL(const char *topic);
diff --git a/src/bin/psql/input.c b/src/bin/psql/input.c
index 1775dffb834..6607d7f162b 100644
--- a/src/bin/psql/input.c
+++ b/src/bin/psql/input.c
@@ -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);
diff --git a/src/bin/psql/input.h b/src/bin/psql/input.h
index 938170ee83b..675953efb4e 100644
--- a/src/bin/psql/input.h
+++ b/src/bin/psql/input.h
@@ -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);
diff --git a/src/bin/psql/large_obj.c b/src/bin/psql/large_obj.c
index befa4c452c3..d1b3af044f4 100644
--- a/src/bin/psql/large_obj.c
+++ b/src/bin/psql/large_obj.c
@@ -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;
diff --git a/src/bin/psql/large_obj.h b/src/bin/psql/large_obj.h
index 3ddb2206bbb..baf1222d8c7 100644
--- a/src/bin/psql/large_obj.h
+++ b/src/bin/psql/large_obj.h
@@ -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 */
diff --git a/src/bin/psql/mainloop.c b/src/bin/psql/mainloop.c
index cb9232d7147..919025cb5c4 100644
--- a/src/bin/psql/mainloop.c
+++ b/src/bin/psql/mainloop.c
@@ -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;
+
+ /* 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 */
+ }
- eof = true;
- continue;
+ 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);
- }
-
- 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 */
+ /* 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);
+
+ new = malloc(len + out_length - (1 + in_length) + 1);
+ if (!new)
+ {
+ perror("malloc");
+ exit(EXIT_FAILURE);
+ }
+
+ 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() */
diff --git a/src/bin/psql/mainloop.h b/src/bin/psql/mainloop.h
index b2b05d7d11b..439703d0404 100644
--- a/src/bin/psql/mainloop.h
+++ b/src/bin/psql/mainloop.h
@@ -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 */
diff --git a/src/bin/psql/prompt.c b/src/bin/psql/prompt.c
index dd41ba54015..d93f5611ced 100644
--- a/src/bin/psql/prompt.c
+++ b/src/bin/psql/prompt.c
@@ -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);
diff --git a/src/bin/psql/prompt.h b/src/bin/psql/prompt.h
index e4c1242deb7..d98116395ad 100644
--- a/src/bin/psql/prompt.h
+++ b/src/bin/psql/prompt.h
@@ -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 */
diff --git a/src/bin/psql/settings.h b/src/bin/psql/settings.h
index 774c54b4594..21f138bd37d 100644
--- a/src/bin/psql/settings.h
+++ b/src/bin/psql/settings.h
@@ -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
diff --git a/src/bin/psql/startup.c b/src/bin/psql/startup.c
index 35f4ddce05c..2599a42199a 100644
--- a/src/bin/psql/startup.c
+++ b/src/bin/psql/startup.c
@@ -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