Commit 7c9390ca authored by Peter Eisentraut's avatar Peter Eisentraut

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

parent 4ceb2d0c
This diff is collapsed.
This diff is collapsed.
...@@ -24,19 +24,18 @@ typedef enum _backslashResult ...@@ -24,19 +24,18 @@ typedef enum _backslashResult
backslashResult HandleSlashCmds(PsqlSettings *pset, backslashResult
const char *line, HandleSlashCmds(const char *line,
PQExpBuffer query_buf, PQExpBuffer query_buf,
const char **end_of_cmd); const char **end_of_cmd);
bool process_file(const char *filename, bool
PsqlSettings *pset); process_file(const char *filename);
bool
bool do_pset(const char *param, do_pset(const char *param,
const char *value, const char *value,
printQueryOpt * popt, printQueryOpt * popt,
bool quiet); bool quiet);
#endif #endif
This diff is collapsed.
...@@ -8,18 +8,15 @@ char * ...@@ -8,18 +8,15 @@ char *
xstrdup(const char *string); xstrdup(const char *string);
bool bool
setQFout(const char *fname, PsqlSettings *pset); setQFout(const char *fname);
char * char *
simple_prompt(const char *prompt, int maxlen, bool echo); simple_prompt(const char *prompt, int maxlen, bool echo);
const char *
interpolate_var(const char *name, PsqlSettings *pset);
PGresult * PGresult *
PSQLexec(PsqlSettings *pset, const char *query); PSQLexec(const char *query);
bool bool
SendQuery(PsqlSettings *pset, const char *query); SendQuery(const char *query);
#endif /* COMMON_H */ #endif /* COMMON_H */
#include <config.h>
#include <c.h> #include <c.h>
#include "copy.h" #include "copy.h"
...@@ -36,7 +35,7 @@ ...@@ -36,7 +35,7 @@
struct copy_options struct copy_options
{ {
char *table; char *table;
char *file; char *file; /* NULL = stdin/stdout */
bool from; bool from;
bool binary; bool binary;
bool oids; bool oids;
...@@ -59,7 +58,7 @@ free_copy_options(struct copy_options * ptr) ...@@ -59,7 +58,7 @@ free_copy_options(struct copy_options * ptr)
static struct copy_options * static struct copy_options *
parse_slash_copy(const char *args, PsqlSettings *pset) parse_slash_copy(const char *args)
{ {
struct copy_options *result; struct copy_options *result;
char *line; char *line;
...@@ -132,17 +131,15 @@ parse_slash_copy(const char *args, PsqlSettings *pset) ...@@ -132,17 +131,15 @@ parse_slash_copy(const char *args, PsqlSettings *pset)
if (!error) if (!error)
{ {
token = strtokx(NULL, " \t", "'", '\\', NULL, NULL); token = strtokx(NULL, " \t", "'", '\\', &quote, NULL);
if (!token) if (!token)
error = true; error = true;
else else if (!quote && (strcasecmp(token, "stdin")==0 || strcasecmp(token, "stdout")==0))
result->file = NULL;
else
result->file = xstrdup(token); result->file = xstrdup(token);
} }
#ifdef USE_ASSERT_CHECKING
assert(error || result->file);
#endif
if (!error) if (!error)
{ {
token = strtokx(NULL, " \t", NULL, '\\', NULL, NULL); token = strtokx(NULL, " \t", NULL, '\\', NULL, NULL);
...@@ -194,8 +191,8 @@ parse_slash_copy(const char *args, PsqlSettings *pset) ...@@ -194,8 +191,8 @@ parse_slash_copy(const char *args, PsqlSettings *pset)
if (error) if (error)
{ {
if (!pset->cur_cmd_interactive) if (!pset.cur_cmd_interactive)
fprintf(stderr, "%s: ", pset->progname); fprintf(stderr, "%s: ", pset.progname);
fputs("\\copy: parse error at ", stderr); fputs("\\copy: parse error at ", stderr);
if (!token) if (!token)
fputs("end of line", stderr); fputs("end of line", stderr);
...@@ -217,7 +214,7 @@ parse_slash_copy(const char *args, PsqlSettings *pset) ...@@ -217,7 +214,7 @@ parse_slash_copy(const char *args, PsqlSettings *pset)
* file or route its response into the file. * file or route its response into the file.
*/ */
bool bool
do_copy(const char *args, PsqlSettings *pset) do_copy(const char *args)
{ {
char query[128 + NAMEDATALEN]; char query[128 + NAMEDATALEN];
FILE *copystream; FILE *copystream;
...@@ -226,7 +223,7 @@ do_copy(const char *args, PsqlSettings *pset) ...@@ -226,7 +223,7 @@ do_copy(const char *args, PsqlSettings *pset)
bool success; bool success;
/* parse options */ /* parse options */
options = parse_slash_copy(args, pset); options = parse_slash_copy(args);
if (!options) if (!options)
return false; return false;
...@@ -242,9 +239,9 @@ do_copy(const char *args, PsqlSettings *pset) ...@@ -242,9 +239,9 @@ do_copy(const char *args, PsqlSettings *pset)
strcat(query, "WITH OIDS "); strcat(query, "WITH OIDS ");
if (options->from) if (options->from)
strcat(query, "FROM stdin"); strcat(query, "FROM STDIN");
else else
strcat(query, "TO stdout"); strcat(query, "TO STDOUT");
if (options->delim) if (options->delim)
...@@ -254,24 +251,32 @@ do_copy(const char *args, PsqlSettings *pset) ...@@ -254,24 +251,32 @@ do_copy(const char *args, PsqlSettings *pset)
strcat(query, "'"); strcat(query, "'");
} }
if (options->null)
{
strcat(query, " WITH NULL AS '");
strcat(query, options->null);
strcat(query, "'");
}
if (options->from) if (options->from)
#ifndef __CYGWIN32__ {
copystream = fopen(options->file, "r"); if (options->file)
#else copystream = fopen(options->file, "r");
copystream = fopen(options->file, "rb"); else
#endif copystream = stdin;
}
else else
#ifndef __CYGWIN32__ {
copystream = fopen(options->file, "w"); if (options->file)
#else copystream = fopen(options->file, "w");
copystream = fopen(options->file, "wb"); else
#endif copystream = stdout;
}
if (!copystream) if (!copystream)
{ {
if (!pset->cur_cmd_interactive) if (!pset.cur_cmd_interactive)
fprintf(stderr, "%s: ", pset->progname); fprintf(stderr, "%s: ", pset.progname);
fprintf(stderr, fprintf(stderr,
"unable to open file %s: %s\n", "unable to open file %s: %s\n",
options->file, strerror(errno)); options->file, strerror(errno));
...@@ -279,40 +284,40 @@ do_copy(const char *args, PsqlSettings *pset) ...@@ -279,40 +284,40 @@ do_copy(const char *args, PsqlSettings *pset)
return false; return false;
} }
result = PSQLexec(pset, query); result = PSQLexec(query);
switch (PQresultStatus(result)) switch (PQresultStatus(result))
{ {
case PGRES_COPY_OUT: case PGRES_COPY_OUT:
success = handleCopyOut(pset->db, copystream); success = handleCopyOut(pset.db, copystream);
break; break;
case PGRES_COPY_IN: case PGRES_COPY_IN:
success = handleCopyIn(pset->db, copystream, NULL); success = handleCopyIn(pset.db, copystream, NULL);
break; break;
case PGRES_NONFATAL_ERROR: case PGRES_NONFATAL_ERROR:
case PGRES_FATAL_ERROR: case PGRES_FATAL_ERROR:
case PGRES_BAD_RESPONSE: case PGRES_BAD_RESPONSE:
success = false; success = false;
fputs(PQerrorMessage(pset->db), stderr); fputs(PQerrorMessage(pset.db), stderr);
break; break;
default: default:
success = false; success = false;
if (!pset->cur_cmd_interactive) if (!pset.cur_cmd_interactive)
fprintf(stderr, "%s: ", pset->progname); fprintf(stderr, "%s: ", pset.progname);
fprintf(stderr, "\\copy: unexpected response (%d)\n", PQresultStatus(result)); fprintf(stderr, "\\copy: unexpected response (%d)\n", PQresultStatus(result));
} }
PQclear(result); PQclear(result);
if (!GetVariable(pset->vars, "quiet")) if (!success)
{ {
if (success) if (!pset.cur_cmd_interactive)
puts("Successfully copied"); fprintf(stderr, "%s: ", pset.progname);
else fprintf(stderr, "\\copy failed\n");
puts("Copy failed");
} }
fclose(copystream); if (copystream != stdout && copystream != stdin)
fclose(copystream);
free_copy_options(options); free_copy_options(options);
return success; return success;
} }
...@@ -396,7 +401,7 @@ handleCopyIn(PGconn *conn, FILE *copystream, const char *prompt) ...@@ -396,7 +401,7 @@ handleCopyIn(PGconn *conn, FILE *copystream, const char *prompt)
while (!copydone) while (!copydone)
{ /* for each input line ... */ { /* for each input line ... */
if (prompt && isatty(fileno(stdin))) if (prompt && isatty(fileno(copystream)))
{ {
fputs(prompt, stdout); fputs(prompt, stdout);
fflush(stdout); fflush(stdout);
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
/* handler for \copy */ /* handler for \copy */
bool bool
do_copy(const char *args, PsqlSettings *pset); do_copy(const char *args);
/* lower level processors for copy in/out streams */ /* lower level processors for copy in/out streams */
......
This diff is collapsed.
...@@ -5,30 +5,30 @@ ...@@ -5,30 +5,30 @@
#include "settings.h" #include "settings.h"
/* \da */ /* \da */
bool describeAggregates(const char *name, PsqlSettings *pset); bool describeAggregates(const char *name);
/* \df */ /* \df */
bool describeFunctions(const char *name, PsqlSettings *pset, bool verbose); bool describeFunctions(const char *name, bool verbose);
/* \dT */ /* \dT */
bool describeTypes(const char *name, PsqlSettings *pset, bool verbose); bool describeTypes(const char *name, bool verbose);
/* \do */ /* \do */
bool describeOperators(const char *name, PsqlSettings *pset); bool describeOperators(const char *name);
/* \z (or \dp) */ /* \z (or \dp) */
bool permissionsList(const char *name, PsqlSettings *pset); bool permissionsList(const char *name);
/* \dd */ /* \dd */
bool objectDescription(const char *object, PsqlSettings *pset); bool objectDescription(const char *object);
/* \d foo */ /* \d foo */
bool describeTableDetails(const char *name, PsqlSettings *pset, bool desc); bool describeTableDetails(const char *name, bool desc);
/* \l */ /* \l */
bool listAllDbs(PsqlSettings *pset, bool desc); bool listAllDbs(bool desc);
/* \dt, \di, \ds, \dS, etc. */ /* \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 */ #endif /* DESCRIBE_H */
...@@ -149,7 +149,7 @@ struct winsize ...@@ -149,7 +149,7 @@ struct winsize
#endif #endif
void void
slashUsage(PsqlSettings *pset) slashUsage(void)
{ {
bool usePipe = false; bool usePipe = false;
const char *pagerenv; const char *pagerenv;
...@@ -157,7 +157,7 @@ slashUsage(PsqlSettings *pset) ...@@ -157,7 +157,7 @@ slashUsage(PsqlSettings *pset)
struct winsize screen_size; struct winsize screen_size;
#ifdef TIOCGWINSZ #ifdef TIOCGWINSZ
if (pset->notty == 0 && if (pset.notty == 0 &&
(ioctl(fileno(stdout), TIOCGWINSZ, &screen_size) == -1 || (ioctl(fileno(stdout), TIOCGWINSZ, &screen_size) == -1 ||
screen_size.ws_col == 0 || screen_size.ws_col == 0 ||
screen_size.ws_row == 0)) screen_size.ws_row == 0))
...@@ -169,7 +169,7 @@ slashUsage(PsqlSettings *pset) ...@@ -169,7 +169,7 @@ slashUsage(PsqlSettings *pset)
} }
#endif #endif
if (pset->notty == 0 && if (pset.notty == 0 &&
(pagerenv = getenv("PAGER")) && (pagerenv = getenv("PAGER")) &&
(pagerenv[0] != '\0') && (pagerenv[0] != '\0') &&
screen_size.ws_row <= 36 && screen_size.ws_row <= 36 &&
...@@ -184,7 +184,7 @@ slashUsage(PsqlSettings *pset) ...@@ -184,7 +184,7 @@ slashUsage(PsqlSettings *pset)
/* if you add/remove a line here, change the row test above */ /* if you add/remove a line here, change the row test above */
fprintf(fout, " \\? help\n"); fprintf(fout, " \\? help\n");
fprintf(fout, " \\c[onnect] [dbname|- [user|?]]\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, " \\copy ... perform SQL COPY with data stream to the client machine");
fprintf(fout, " \\copyright show PostgreSQL usage and distribution terms\n"); fprintf(fout, " \\copyright show PostgreSQL usage and distribution terms\n");
fprintf(fout, " \\d <table> describe table (or view, index, sequence)\n"); fprintf(fout, " \\d <table> describe table (or view, index, sequence)\n");
...@@ -209,9 +209,10 @@ slashUsage(PsqlSettings *pset) ...@@ -209,9 +209,10 @@ slashUsage(PsqlSettings *pset)
fprintf(fout, " \\qecho <text> write text to query output stream (see \\o)\n"); fprintf(fout, " \\qecho <text> write text to query output stream (see \\o)\n");
fprintf(fout, " \\r reset (clear) the query buffer\n"); fprintf(fout, " \\r reset (clear) the query buffer\n");
fprintf(fout, " \\s [fname] print history or save it in <fname>\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, " \\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, " \\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, " \\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, " \\w <fname> write current query buffer to a file\n");
fprintf(fout, " \\z list table access permissions\n"); fprintf(fout, " \\z list table access permissions\n");
fprintf(fout, " \\! [cmd] shell escape or command\n"); fprintf(fout, " \\! [cmd] shell escape or command\n");
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
void usage(void); void usage(void);
void slashUsage(PsqlSettings *pset); void slashUsage(void);
void helpSQL(const char *topic); void helpSQL(const char *topic);
......
...@@ -29,6 +29,10 @@ char * ...@@ -29,6 +29,10 @@ char *
gets_interactive(const char *prompt) gets_interactive(const char *prompt)
{ {
char *s; char *s;
#ifdef USE_HISTORY
const char *var;
static char * prev_hist = NULL;
#endif
#ifdef USE_READLINE #ifdef USE_READLINE
if (useReadline) if (useReadline)
...@@ -44,8 +48,19 @@ gets_interactive(const char *prompt) ...@@ -44,8 +48,19 @@ gets_interactive(const char *prompt)
#endif #endif
#ifdef USE_HISTORY #ifdef USE_HISTORY
if (useHistory && s && s[0] != '\0') if (useHistory && s && s[0] != '\0')
add_history(s); {
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 #endif
return s; return s;
...@@ -93,14 +108,14 @@ gets_fromFile(FILE *source) ...@@ -93,14 +108,14 @@ gets_fromFile(FILE *source)
* The only "flag" right now is 1 for use readline & history. * The only "flag" right now is 1 for use readline & history.
*/ */
void void
initializeInput(int flags, PsqlSettings *pset) initializeInput(int flags)
{ {
#ifdef USE_READLINE #ifdef USE_READLINE
if (flags == 1) if (flags == 1)
{ {
useReadline = true; useReadline = true;
rl_readline_name = "psql"; rl_readline_name = "psql";
initialize_readline(&(pset->db)); initialize_readline(&(pset.db));
} }
#endif #endif
...@@ -110,6 +125,7 @@ initializeInput(int flags, PsqlSettings *pset) ...@@ -110,6 +125,7 @@ initializeInput(int flags, PsqlSettings *pset)
const char *home; const char *home;
useHistory = true; useHistory = true;
SetVariable(pset.vars, "HISTSIZE", "500");
using_history(); using_history();
home = getenv("HOME"); home = getenv("HOME");
if (home) if (home)
...@@ -166,6 +182,9 @@ finishInput(void) ...@@ -166,6 +182,9 @@ finishInput(void)
psql_history = (char *) malloc(strlen(home) + 20); psql_history = (char *) malloc(strlen(home) + 20);
if (psql_history) if (psql_history)
{ {
const char * var = GetVariable(pset.vars, "HISTSIZE");
if (var)
stifle_history(atoi(var));
sprintf(psql_history, "%s/.psql_history", home); sprintf(psql_history, "%s/.psql_history", home);
write_history(psql_history); write_history(psql_history);
free(psql_history); free(psql_history);
......
...@@ -42,7 +42,7 @@ char * gets_interactive(const char *prompt); ...@@ -42,7 +42,7 @@ char * gets_interactive(const char *prompt);
char * gets_fromFile(FILE *source); char * gets_fromFile(FILE *source);
void initializeInput(int flags, PsqlSettings *pset); void initializeInput(int flags);
bool saveHistory(const char *fname); bool saveHistory(const char *fname);
......
#include <config.h>
#include <c.h> #include <c.h>
#include "large_obj.h" #include "large_obj.h"
...@@ -33,9 +32,9 @@ _my_notice_handler(void *arg, const char *message) ...@@ -33,9 +32,9 @@ _my_notice_handler(void *arg, const char *message)
static bool 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; PGresult *res;
bool commit; bool commit;
PQnoticeProcessor old_notice_hook; PQnoticeProcessor old_notice_hook;
...@@ -46,9 +45,9 @@ handle_transaction(PsqlSettings *pset) ...@@ -46,9 +45,9 @@ handle_transaction(PsqlSettings *pset)
commit = (var && strcmp(var, "commit") == 0); commit = (var && strcmp(var, "commit") == 0);
notice[0] = '\0'; notice[0] = '\0';
old_notice_hook = PQsetNoticeProcessor(pset->db, _my_notice_handler, NULL); old_notice_hook = PQsetNoticeProcessor(pset.db, _my_notice_handler, NULL);
res = PSQLexec(pset, commit ? "COMMIT" : "ROLLBACK"); res = PSQLexec(commit ? "COMMIT" : "ROLLBACK");
if (!res) if (!res)
return false; return false;
...@@ -58,7 +57,7 @@ handle_transaction(PsqlSettings *pset) ...@@ -58,7 +57,7 @@ handle_transaction(PsqlSettings *pset)
(commit && strcmp(notice, "NOTICE: EndTransactionBlock and not inprogress/abort state\n") != 0)) (commit && strcmp(notice, "NOTICE: EndTransactionBlock and not inprogress/abort state\n") != 0))
fputs(notice, stderr); fputs(notice, stderr);
} }
else if (!GetVariableBool(pset->vars, "quiet")) else if (!QUIET())
{ {
if (commit) if (commit)
puts("Warning: Your transaction in progress has been committed."); puts("Warning: Your transaction in progress has been committed.");
...@@ -66,7 +65,7 @@ handle_transaction(PsqlSettings *pset) ...@@ -66,7 +65,7 @@ handle_transaction(PsqlSettings *pset)
puts("Warning: Your transaction in progress has been rolled back."); 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; return true;
} }
...@@ -78,43 +77,43 @@ handle_transaction(PsqlSettings *pset) ...@@ -78,43 +77,43 @@ handle_transaction(PsqlSettings *pset)
* Write a large object to a file * Write a large object to a file
*/ */
bool 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; PGresult *res;
int status; int status;
bool own_transaction = true; 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) if (var && strcmp(var, "nothing") == 0)
own_transaction = false; own_transaction = false;
if (!pset->db) if (!pset.db)
{ {
if (!pset->cur_cmd_interactive) if (!pset.cur_cmd_interactive)
fprintf(stderr, "%s: ", pset->progname); fprintf(stderr, "%s: ", pset.progname);
fputs("\\lo_export: not connected to a database\n", stderr); fputs("\\lo_export: not connected to a database\n", stderr);
return false; return false;
} }
if (own_transaction) if (own_transaction)
{ {
if (!handle_transaction(pset)) if (!handle_transaction())
return false; return false;
if (!(res = PSQLexec(pset, "BEGIN"))) if (!(res = PSQLexec("BEGIN")))
return false; return false;
PQclear(res); 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) if (status != 1)
{ /* of course this status is documented { /* of course this status is documented
* nowhere :( */ * nowhere :( */
fputs(PQerrorMessage(pset->db), stderr); fputs(PQerrorMessage(pset.db), stderr);
if (own_transaction) if (own_transaction)
{ {
res = PQexec(pset->db, "ROLLBACK"); res = PQexec(pset.db, "ROLLBACK");
PQclear(res); PQclear(res);
} }
return false; return false;
...@@ -122,9 +121,9 @@ do_lo_export(PsqlSettings *pset, const char *loid_arg, const char *filename_arg) ...@@ -122,9 +121,9 @@ do_lo_export(PsqlSettings *pset, const char *loid_arg, const char *filename_arg)
if (own_transaction) if (own_transaction)
{ {
if (!(res = PSQLexec(pset, "COMMIT"))) if (!(res = PSQLexec("COMMIT")))
{ {
res = PQexec(pset->db, "ROLLBACK"); res = PQexec(pset.db, "ROLLBACK");
PQclear(res); PQclear(res);
return false; return false;
} }
...@@ -132,7 +131,7 @@ do_lo_export(PsqlSettings *pset, const char *loid_arg, const char *filename_arg) ...@@ -132,7 +131,7 @@ do_lo_export(PsqlSettings *pset, const char *loid_arg, const char *filename_arg)
PQclear(res); PQclear(res);
} }
fprintf(pset->queryFout, "lo_export\n"); fprintf(pset.queryFout, "lo_export\n");
return true; return true;
} }
...@@ -145,44 +144,44 @@ do_lo_export(PsqlSettings *pset, const char *loid_arg, const char *filename_arg) ...@@ -145,44 +144,44 @@ do_lo_export(PsqlSettings *pset, const char *loid_arg, const char *filename_arg)
* Copy large object from file to database * Copy large object from file to database
*/ */
bool 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; PGresult *res;
Oid loid; Oid loid;
char buf[1024]; char buf[1024];
unsigned int i; unsigned int i;
bool own_transaction = true; 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) if (var && strcmp(var, "nothing") == 0)
own_transaction = false; own_transaction = false;
if (!pset->db) if (!pset.db)
{ {
if (!pset->cur_cmd_interactive) if (!pset.cur_cmd_interactive)
fprintf(stderr, "%s: ", pset->progname); fprintf(stderr, "%s: ", pset.progname);
fputs("\\lo_import: not connected to a database\n", stderr); fputs("\\lo_import: not connected to a database\n", stderr);
return false; return false;
} }
if (own_transaction) if (own_transaction)
{ {
if (!handle_transaction(pset)) if (!handle_transaction())
return false; return false;
if (!(res = PSQLexec(pset, "BEGIN"))) if (!(res = PSQLexec("BEGIN")))
return false; return false;
PQclear(res); PQclear(res);
} }
loid = lo_import(pset->db, (char *) filename_arg); loid = lo_import(pset.db, (char *) filename_arg);
if (loid == InvalidOid) if (loid == InvalidOid)
{ {
fputs(PQerrorMessage(pset->db), stderr); fputs(PQerrorMessage(pset.db), stderr);
if (own_transaction) if (own_transaction)
{ {
res = PQexec(pset->db, "ROLLBACK"); res = PQexec(pset.db, "ROLLBACK");
PQclear(res); PQclear(res);
} }
return false; return false;
...@@ -199,11 +198,11 @@ do_lo_import(PsqlSettings *pset, const char *filename_arg, const char *comment_a ...@@ -199,11 +198,11 @@ do_lo_import(PsqlSettings *pset, const char *filename_arg, const char *comment_a
strncat(buf, &comment_arg[i], 1); strncat(buf, &comment_arg[i], 1);
strcat(buf, "')"); strcat(buf, "')");
if (!(res = PSQLexec(pset, buf))) if (!(res = PSQLexec(buf)))
{ {
if (own_transaction) if (own_transaction)
{ {
res = PQexec(pset->db, "ROLLBACK"); res = PQexec(pset.db, "ROLLBACK");
PQclear(res); PQclear(res);
} }
return false; return false;
...@@ -212,9 +211,9 @@ do_lo_import(PsqlSettings *pset, const char *filename_arg, const char *comment_a ...@@ -212,9 +211,9 @@ do_lo_import(PsqlSettings *pset, const char *filename_arg, const char *comment_a
if (own_transaction) if (own_transaction)
{ {
if (!(res = PSQLexec(pset, "COMMIT"))) if (!(res = PSQLexec("COMMIT")))
{ {
res = PQexec(pset->db, "ROLLBACK"); res = PQexec(pset.db, "ROLLBACK");
PQclear(res); PQclear(res);
return false; return false;
} }
...@@ -223,8 +222,9 @@ do_lo_import(PsqlSettings *pset, const char *filename_arg, const char *comment_a ...@@ -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); fprintf(pset.queryFout, "lo_import %d\n", loid);
pset->lastOid = loid; sprintf(buf, "%u", (unsigned int)loid);
SetVariable(pset.vars, "LASTOID", buf);
return true; return true;
} }
...@@ -237,44 +237,44 @@ do_lo_import(PsqlSettings *pset, const char *filename_arg, const char *comment_a ...@@ -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 * removes a large object out of the database
*/ */
bool bool
do_lo_unlink(PsqlSettings *pset, const char *loid_arg) do_lo_unlink(const char *loid_arg)
{ {
PGresult *res; PGresult *res;
int status; int status;
Oid loid = (Oid) atol(loid_arg); Oid loid = (Oid) atol(loid_arg);
char buf[256]; char buf[256];
bool own_transaction = true; 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) if (var && strcmp(var, "nothing") == 0)
own_transaction = false; own_transaction = false;
if (!pset->db) if (!pset.db)
{ {
if (!pset->cur_cmd_interactive) if (!pset.cur_cmd_interactive)
fprintf(stderr, "%s: ", pset->progname); fprintf(stderr, "%s: ", pset.progname);
fputs("\\lo_unlink: not connected to a database\n", stderr); fputs("\\lo_unlink: not connected to a database\n", stderr);
return false; return false;
} }
if (own_transaction) if (own_transaction)
{ {
if (!handle_transaction(pset)) if (!handle_transaction())
return false; return false;
if (!(res = PSQLexec(pset, "BEGIN"))) if (!(res = PSQLexec("BEGIN")))
return false; return false;
PQclear(res); PQclear(res);
} }
status = lo_unlink(pset->db, loid); status = lo_unlink(pset.db, loid);
if (status == -1) if (status == -1)
{ {
fputs(PQerrorMessage(pset->db), stderr); fputs(PQerrorMessage(pset.db), stderr);
if (own_transaction) if (own_transaction)
{ {
res = PQexec(pset->db, "ROLLBACK"); res = PQexec(pset.db, "ROLLBACK");
PQclear(res); PQclear(res);
} }
return false; return false;
...@@ -282,11 +282,11 @@ do_lo_unlink(PsqlSettings *pset, const char *loid_arg) ...@@ -282,11 +282,11 @@ do_lo_unlink(PsqlSettings *pset, const char *loid_arg)
/* remove the comment as well */ /* remove the comment as well */
sprintf(buf, "DELETE FROM pg_description WHERE objoid = %d", loid); sprintf(buf, "DELETE FROM pg_description WHERE objoid = %d", loid);
if (!(res = PSQLexec(pset, buf))) if (!(res = PSQLexec(buf)))
{ {
if (own_transaction) if (own_transaction)
{ {
res = PQexec(pset->db, "ROLLBACK"); res = PQexec(pset.db, "ROLLBACK");
PQclear(res); PQclear(res);
} }
return false; return false;
...@@ -295,9 +295,9 @@ do_lo_unlink(PsqlSettings *pset, const char *loid_arg) ...@@ -295,9 +295,9 @@ do_lo_unlink(PsqlSettings *pset, const char *loid_arg)
if (own_transaction) if (own_transaction)
{ {
if (!(res = PSQLexec(pset, "COMMIT"))) if (!(res = PSQLexec("COMMIT")))
{ {
res = PQexec(pset->db, "ROLLBACK"); res = PQexec(pset.db, "ROLLBACK");
PQclear(res); PQclear(res);
return false; return false;
} }
...@@ -305,7 +305,7 @@ do_lo_unlink(PsqlSettings *pset, const char *loid_arg) ...@@ -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; return true;
} }
...@@ -318,11 +318,11 @@ do_lo_unlink(PsqlSettings *pset, const char *loid_arg) ...@@ -318,11 +318,11 @@ do_lo_unlink(PsqlSettings *pset, const char *loid_arg)
* Show all large objects in database with comments * Show all large objects in database with comments
*/ */
bool bool
do_lo_list(PsqlSettings *pset) do_lo_list(void)
{ {
PGresult *res; PGresult *res;
char buf[1024]; char buf[1024];
printQueryOpt myopt = pset->popt; printQueryOpt myopt = pset.popt;
strcpy(buf, strcpy(buf,
"SELECT usename as \"Owner\", substring(relname from 5) as \"ID\",\n" "SELECT usename as \"Owner\", substring(relname from 5) as \"ID\",\n"
...@@ -336,7 +336,7 @@ do_lo_list(PsqlSettings *pset) ...@@ -336,7 +336,7 @@ do_lo_list(PsqlSettings *pset)
"WHERE not exists (select 1 from pg_user where usesysid = relowner) AND relkind = 'l'\n" "WHERE not exists (select 1 from pg_user where usesysid = relowner) AND relkind = 'l'\n"
"ORDER BY \"ID\""); "ORDER BY \"ID\"");
res = PSQLexec(pset, buf); res = PSQLexec(buf);
if (!res) if (!res)
return false; return false;
...@@ -344,7 +344,7 @@ do_lo_list(PsqlSettings *pset) ...@@ -344,7 +344,7 @@ do_lo_list(PsqlSettings *pset)
myopt.nullPrint = NULL; myopt.nullPrint = NULL;
myopt.title = "Large objects"; myopt.title = "Large objects";
printQuery(res, &myopt, pset->queryFout); printQuery(res, &myopt, pset.queryFout);
PQclear(res); PQclear(res);
return true; return true;
......
...@@ -2,11 +2,10 @@ ...@@ -2,11 +2,10 @@
#define LARGE_OBJ_H #define LARGE_OBJ_H
#include <c.h> #include <c.h>
#include "settings.h"
bool do_lo_export(PsqlSettings *pset, const char *loid_arg, const char *filename_arg); bool do_lo_export(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_import(const char *filename_arg, const char *comment_arg);
bool do_lo_unlink(PsqlSettings *pset, const char *loid_arg); bool do_lo_unlink(const char *loid_arg);
bool do_lo_list(PsqlSettings *pset); bool do_lo_list(void);
#endif /* LARGE_OBJ_H */ #endif /* LARGE_OBJ_H */
#include <config.h>
#include <c.h> #include <c.h>
#include "mainloop.h" #include "mainloop.h"
...@@ -26,7 +25,7 @@ ...@@ -26,7 +25,7 @@
* FIXME: rewrite this whole thing with flex * FIXME: rewrite this whole thing with flex
*/ */
int int
MainLoop(PsqlSettings *pset, FILE *source) MainLoop(FILE *source)
{ {
PQExpBuffer query_buf; /* buffer for query being accumulated */ PQExpBuffer query_buf; /* buffer for query being accumulated */
PQExpBuffer previous_buf; /* if there isn't anything in the new buffer PQExpBuffer previous_buf; /* if there isn't anything in the new buffer
...@@ -36,13 +35,14 @@ MainLoop(PsqlSettings *pset, FILE *source) ...@@ -36,13 +35,14 @@ MainLoop(PsqlSettings *pset, FILE *source)
int successResult = EXIT_SUCCESS; int successResult = EXIT_SUCCESS;
backslashResult slashCmdStatus; backslashResult slashCmdStatus;
bool eof = false; /* end of our command input? */
bool success; bool success;
char in_quote; /* == 0 for no in_quote */ char in_quote; /* == 0 for no in_quote */
bool was_bslash; /* backslash */ bool was_bslash; /* backslash */
bool xcomment; /* in extended comment */ bool xcomment; /* in extended comment */
int paren_level; int paren_level;
unsigned int query_start; unsigned int query_start;
int count_eof;
const char *var;
int i, int i,
prevlen, prevlen,
...@@ -56,12 +56,12 @@ MainLoop(PsqlSettings *pset, FILE *source) ...@@ -56,12 +56,12 @@ MainLoop(PsqlSettings *pset, FILE *source)
/* Save old settings */ /* Save old settings */
prev_cmd_source = pset->cur_cmd_source; prev_cmd_source = pset.cur_cmd_source;
prev_cmd_interactive = pset->cur_cmd_interactive; prev_cmd_interactive = pset.cur_cmd_interactive;
/* Establish new source */ /* Establish new source */
pset->cur_cmd_source = source; pset.cur_cmd_source = source;
pset->cur_cmd_interactive = ((source == stdin) && !pset->notty); pset.cur_cmd_interactive = ((source == stdin) && !pset.notty);
query_buf = createPQExpBuffer(); query_buf = createPQExpBuffer();
...@@ -79,7 +79,7 @@ MainLoop(PsqlSettings *pset, FILE *source) ...@@ -79,7 +79,7 @@ MainLoop(PsqlSettings *pset, FILE *source)
/* main loop to get queries and execute them */ /* main loop to get queries and execute them */
while (!eof) while (1)
{ {
if (slashCmdStatus == CMD_NEWEDIT) if (slashCmdStatus == CMD_NEWEDIT)
{ {
...@@ -102,7 +102,7 @@ MainLoop(PsqlSettings *pset, FILE *source) ...@@ -102,7 +102,7 @@ MainLoop(PsqlSettings *pset, FILE *source)
* otherwise, set interactive prompt if necessary and get * otherwise, set interactive prompt if necessary and get
* another line * another line
*/ */
if (pset->cur_cmd_interactive) if (pset.cur_cmd_interactive)
{ {
int prompt_status; int prompt_status;
...@@ -117,7 +117,7 @@ MainLoop(PsqlSettings *pset, FILE *source) ...@@ -117,7 +117,7 @@ MainLoop(PsqlSettings *pset, FILE *source)
else else
prompt_status = PROMPT_READY; prompt_status = PROMPT_READY;
line = gets_interactive(get_prompt(pset, prompt_status)); line = gets_interactive(get_prompt(prompt_status));
} }
else else
line = gets_fromFile(source); line = gets_fromFile(source);
...@@ -125,7 +125,7 @@ MainLoop(PsqlSettings *pset, FILE *source) ...@@ -125,7 +125,7 @@ MainLoop(PsqlSettings *pset, FILE *source)
/* Setting this will not have effect until next line. */ /* 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 * query_buf holds query already accumulated. line is the
...@@ -137,14 +137,47 @@ MainLoop(PsqlSettings *pset, FILE *source) ...@@ -137,14 +137,47 @@ MainLoop(PsqlSettings *pset, FILE *source)
/* No more input. Time to quit, or \i done */ /* No more input. Time to quit, or \i done */
if (line == NULL) if (line == NULL)
{ {
if (GetVariableBool(pset->vars, "echo") && !GetVariableBool(pset->vars, "quiet")) if (pset.cur_cmd_interactive)
puts("EOF"); {
else if (pset->cur_cmd_interactive) bool getout = true;
putc('\n', stdout); /* just newline */
/* 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; if (getout)
continue; {
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 */ /* strip trailing backslashes, they don't have a clear meaning */
while (1) while (1)
...@@ -164,11 +197,11 @@ MainLoop(PsqlSettings *pset, FILE *source) ...@@ -164,11 +197,11 @@ MainLoop(PsqlSettings *pset, FILE *source)
continue; continue;
} }
/* echo back if flag is set */
/* echo back if input is from file and flag is set */ var = GetVariable(pset.vars, "ECHO");
if (!pset->cur_cmd_interactive && GetVariableBool(pset->vars, "echo")) if (var && strcmp(var, "full")==0)
puts(line); puts(line);
fflush(stdout);
len = strlen(line); len = strlen(line);
query_start = 0; query_start = 0;
...@@ -236,8 +269,7 @@ MainLoop(PsqlSettings *pset, FILE *source) ...@@ -236,8 +269,7 @@ MainLoop(PsqlSettings *pset, FILE *source)
/* colon -> substitute variable */ /* colon -> substitute variable */
/* we need to be on the watch for the '::' operator */ /* we need to be on the watch for the '::' operator */
else if (line[i] == ':' && !was_bslash && else if (line[i] == ':' && !was_bslash &&
strspn(line+i+thislen, VALID_VARIABLE_CHARS)>0 && strspn(line+i+thislen, VALID_VARIABLE_CHARS)>0
(prevlen > 0 && line[i-prevlen]!=':')
) )
{ {
size_t in_length, size_t in_length,
...@@ -250,24 +282,35 @@ MainLoop(PsqlSettings *pset, FILE *source) ...@@ -250,24 +282,35 @@ MainLoop(PsqlSettings *pset, FILE *source)
in_length = strspn(&line[i + thislen], VALID_VARIABLE_CHARS); in_length = strspn(&line[i + thislen], VALID_VARIABLE_CHARS);
after = line[i + thislen + in_length]; after = line[i + thislen + in_length];
line[i + thislen + in_length] = '\0'; 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); /* if the variable doesn't exist we'll leave the string as is */
line = new; value = GetVariable(pset.vars, &line[i + thislen]);
len = strlen(new); if (value)
continue; /* reparse the just substituted */ {
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 */ /* semicolon? then send query */
...@@ -288,7 +331,7 @@ MainLoop(PsqlSettings *pset, FILE *source) ...@@ -288,7 +331,7 @@ MainLoop(PsqlSettings *pset, FILE *source)
} }
/* execute query */ /* execute query */
success = SendQuery(pset, query_buf->data); success = SendQuery(query_buf->data);
slashCmdStatus = success ? CMD_SEND : CMD_ERROR; slashCmdStatus = success ? CMD_SEND : CMD_ERROR;
resetPQExpBuffer(previous_buf); resetPQExpBuffer(previous_buf);
...@@ -314,7 +357,7 @@ MainLoop(PsqlSettings *pset, FILE *source) ...@@ -314,7 +357,7 @@ MainLoop(PsqlSettings *pset, FILE *source)
paren_level = 0; paren_level = 0;
line[i - prevlen] = '\0'; /* overwrites backslash */ 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') if (line[query_start + strspn(line + query_start, " \t")] != '\0')
{ {
/* /*
...@@ -328,7 +371,7 @@ MainLoop(PsqlSettings *pset, FILE *source) ...@@ -328,7 +371,7 @@ MainLoop(PsqlSettings *pset, FILE *source)
} }
/* handle backslash command */ /* handle backslash command */
slashCmdStatus = HandleSlashCmds(pset, &line[i], slashCmdStatus = HandleSlashCmds(&line[i],
query_buf->len>0 ? query_buf : previous_buf, query_buf->len>0 ? query_buf : previous_buf,
&end_of_cmd); &end_of_cmd);
...@@ -342,7 +385,7 @@ MainLoop(PsqlSettings *pset, FILE *source) ...@@ -342,7 +385,7 @@ MainLoop(PsqlSettings *pset, FILE *source)
if (slashCmdStatus == CMD_SEND) if (slashCmdStatus == CMD_SEND)
{ {
success = SendQuery(pset, query_buf->data); success = SendQuery(query_buf->data);
query_start = i + thislen; query_start = i + thislen;
resetPQExpBuffer(previous_buf); resetPQExpBuffer(previous_buf);
...@@ -350,14 +393,9 @@ MainLoop(PsqlSettings *pset, FILE *source) ...@@ -350,14 +393,9 @@ MainLoop(PsqlSettings *pset, FILE *source)
resetPQExpBuffer(query_buf); resetPQExpBuffer(query_buf);
} }
/* is there anything left after the backslash command? */ /* process anything left after the backslash command */
if (end_of_cmd) i += end_of_cmd - &line[i];
{ query_start = i;
i += end_of_cmd - &line[i];
query_start = i;
}
else
break;
} }
...@@ -387,9 +425,9 @@ MainLoop(PsqlSettings *pset, FILE *source) ...@@ -387,9 +425,9 @@ MainLoop(PsqlSettings *pset, FILE *source)
/* In single line mode, send off the query if any */ /* 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; slashCmdStatus = success ? CMD_SEND : CMD_ERROR;
resetPQExpBuffer(previous_buf); resetPQExpBuffer(previous_buf);
appendPQExpBufferStr(previous_buf, query_buf->data); appendPQExpBufferStr(previous_buf, query_buf->data);
...@@ -397,7 +435,7 @@ MainLoop(PsqlSettings *pset, FILE *source) ...@@ -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; successResult = EXIT_USER;
break; break;
...@@ -405,18 +443,18 @@ MainLoop(PsqlSettings *pset, FILE *source) ...@@ -405,18 +443,18 @@ MainLoop(PsqlSettings *pset, FILE *source)
/* Have we lost the db connection? */ /* Have we lost the db connection? */
if (pset->db == NULL && !pset->cur_cmd_interactive) if (pset.db == NULL && !pset.cur_cmd_interactive)
{ {
successResult = EXIT_BADCONN; successResult = EXIT_BADCONN;
break; break;
} }
} /* while !EOF */ } /* while !endofprogram */
destroyPQExpBuffer(query_buf); destroyPQExpBuffer(query_buf);
destroyPQExpBuffer(previous_buf); destroyPQExpBuffer(previous_buf);
pset->cur_cmd_source = prev_cmd_source; pset.cur_cmd_source = prev_cmd_source;
pset->cur_cmd_interactive = prev_cmd_interactive; pset.cur_cmd_interactive = prev_cmd_interactive;
return successResult; return successResult;
} /* MainLoop() */ } /* MainLoop() */
...@@ -2,9 +2,7 @@ ...@@ -2,9 +2,7 @@
#define MAINLOOP_H #define MAINLOOP_H
#include <stdio.h> #include <stdio.h>
#include "settings.h"
int int MainLoop(FILE *source);
MainLoop(PsqlSettings *pset, FILE *source);
#endif /* MAINLOOP_H */ #endif /* MAINLOOP_H */
#include <config.h>
#include <c.h> #include <c.h>
#include "prompt.h" #include "prompt.h"
...@@ -10,6 +9,7 @@ ...@@ -10,6 +9,7 @@
#include "settings.h" #include "settings.h"
#include "common.h" #include "common.h"
#include "variables.h"
#ifdef WIN32 #ifdef WIN32
#define popen(x,y) _popen(x,y) #define popen(x,y) _popen(x,y)
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
* get_prompt * get_prompt
* *
* Returns a statically allocated prompt made by interpolating certain * 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) * (might not be completely multibyte safe)
* *
* Defined interpolations are: * Defined interpolations are:
...@@ -46,8 +46,7 @@ ...@@ -46,8 +46,7 @@
* *
* %`command` - The result of executing command in /bin/sh with trailing * %`command` - The result of executing command in /bin/sh with trailing
* newline stripped. * newline stripped.
* %$name$ - The value of the psql/environment/magic varible 'name' * %$name$ - The value of the psql variable 'name'
* (same rules as for, e.g., \echo $foo)
* (those will not be rescanned for more escape sequences!) * (those will not be rescanned for more escape sequences!)
* *
* *
...@@ -56,7 +55,7 @@ ...@@ -56,7 +55,7 @@
*-------------------------- *--------------------------
*/ */
const char * const char *
get_prompt(PsqlSettings *pset, promptStatus_t status) get_prompt(promptStatus_t status)
{ {
#define MAX_PROMPT_SIZE 256 #define MAX_PROMPT_SIZE 256
static char destination[MAX_PROMPT_SIZE + 1]; static char destination[MAX_PROMPT_SIZE + 1];
...@@ -66,11 +65,11 @@ get_prompt(PsqlSettings *pset, promptStatus_t status) ...@@ -66,11 +65,11 @@ get_prompt(PsqlSettings *pset, promptStatus_t status)
const char *prompt_string; const char *prompt_string;
if (status == PROMPT_READY) 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) 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) else if (status == PROMPT_COPY)
prompt_string = GetVariable(pset->vars, "prompt3"); prompt_string = GetVariable(pset.vars, "PROMPT3");
else else
prompt_string = "? "; prompt_string = "? ";
...@@ -92,31 +91,31 @@ get_prompt(PsqlSettings *pset, promptStatus_t status) ...@@ -92,31 +91,31 @@ get_prompt(PsqlSettings *pset, promptStatus_t status)
/* Current database */ /* Current database */
case '/': case '/':
if (pset->db) if (pset.db)
strncpy(buf, PQdb(pset->db), MAX_PROMPT_SIZE); strncpy(buf, PQdb(pset.db), MAX_PROMPT_SIZE);
break; break;
case '~': case '~':
{ {
const char *var; const char *var;
if (pset->db) if (pset.db)
{ {
if (strcmp(PQdb(pset->db), PQuser(pset->db)) == 0 || if (strcmp(PQdb(pset.db), PQuser(pset.db)) == 0 ||
((var = getenv("PGDATABASE")) && strcmp(var, PQdb(pset->db)) == 0)) ((var = getenv("PGDATABASE")) && strcmp(var, PQdb(pset.db)) == 0))
strcpy(buf, "~"); strcpy(buf, "~");
else else
strncpy(buf, PQdb(pset->db), MAX_PROMPT_SIZE); strncpy(buf, PQdb(pset.db), MAX_PROMPT_SIZE);
} }
break; break;
} }
/* DB server hostname (long/short) */ /* DB server hostname (long/short) */
case 'M': case 'M':
case 'm': case 'm':
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') if (*p == 'm')
buf[strcspn(buf, ".")] = '\0'; buf[strcspn(buf, ".")] = '\0';
} }
...@@ -126,13 +125,13 @@ get_prompt(PsqlSettings *pset, promptStatus_t status) ...@@ -126,13 +125,13 @@ get_prompt(PsqlSettings *pset, promptStatus_t status)
break; break;
/* DB server port number */ /* DB server port number */
case '>': case '>':
if (pset->db && PQport(pset->db)) if (pset.db && PQport(pset.db))
strncpy(buf, PQport(pset->db), MAX_PROMPT_SIZE); strncpy(buf, PQport(pset.db), MAX_PROMPT_SIZE);
break; break;
/* DB server user name */ /* DB server user name */
case 'n': case 'n':
if (pset->db) if (pset.db)
strncpy(buf, PQuser(pset->db), MAX_PROMPT_SIZE); strncpy(buf, PQuser(pset.db), MAX_PROMPT_SIZE);
break; break;
case '0': case '0':
...@@ -159,9 +158,9 @@ get_prompt(PsqlSettings *pset, promptStatus_t status) ...@@ -159,9 +158,9 @@ get_prompt(PsqlSettings *pset, promptStatus_t status)
switch (status) switch (status)
{ {
case PROMPT_READY: case PROMPT_READY:
if (!pset->db) if (!pset.db)
buf[0] = '!'; buf[0] = '!';
else if (!GetVariableBool(pset->vars, "singleline")) else if (!GetVariableBool(pset.vars, "SINGLELINE"))
buf[0] = '='; buf[0] = '=';
else else
buf[0] = '^'; buf[0] = '^';
...@@ -189,7 +188,7 @@ get_prompt(PsqlSettings *pset, promptStatus_t status) ...@@ -189,7 +188,7 @@ get_prompt(PsqlSettings *pset, promptStatus_t status)
case '#': case '#':
{ {
if (pset->db && strcmp(PQuser(pset->db), "postgres") == 0) if (pset.db && strcmp(PQuser(pset.db), "postgres") == 0)
buf[0] = '#'; buf[0] = '#';
else else
buf[0] = '>'; buf[0] = '>';
...@@ -230,7 +229,7 @@ get_prompt(PsqlSettings *pset, promptStatus_t status) ...@@ -230,7 +229,7 @@ get_prompt(PsqlSettings *pset, promptStatus_t status)
name = strdup(p + 1); name = strdup(p + 1);
nameend = strcspn(name, "$"); nameend = strcspn(name, "$");
name[nameend] = '\0'; name[nameend] = '\0';
val = interpolate_var(name, pset); val = GetVariable(pset.vars, name);
if (val) if (val)
strncpy(buf, val, MAX_PROMPT_SIZE); strncpy(buf, val, MAX_PROMPT_SIZE);
free(name); free(name);
......
...@@ -14,7 +14,7 @@ typedef enum _promptStatus ...@@ -14,7 +14,7 @@ typedef enum _promptStatus
} promptStatus_t; } promptStatus_t;
const char * const char *
get_prompt(PsqlSettings *pset, promptStatus_t status); get_prompt(promptStatus_t status);
#endif /* PROMPT_H */ #endif /* PROMPT_H */
...@@ -43,11 +43,13 @@ typedef struct _psqlSettings ...@@ -43,11 +43,13 @@ typedef struct _psqlSettings
bool has_client_encoding; /* was PGCLIENTENCODING set on bool has_client_encoding; /* was PGCLIENTENCODING set on
* startup? */ * startup? */
Oid lastOid; /* saves oid from insert command
because people want it so badly */
char *progname; /* in case you renamed psql */ char *progname; /* in case you renamed psql */
} PsqlSettings; } PsqlSettings;
extern PsqlSettings pset;
#define QUIET() (GetVariableBool(pset.vars, "QUIET"))
#ifndef EXIT_SUCCESS #ifndef EXIT_SUCCESS
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment