Commit 0e6652e6 authored by Bruce Momjian's avatar Bruce Momjian

psql cleanup

parent 2323b636
This diff is collapsed.
...@@ -11,37 +11,34 @@ ...@@ -11,37 +11,34 @@
typedef enum _backslashResult { typedef enum _backslashResult
{
CMD_UNKNOWN = 0, /* not done parsing yet (internal only) */ CMD_UNKNOWN = 0, /* not done parsing yet (internal only) */
CMD_SEND, /* query complete; send off */ CMD_SEND, /* query complete; send off */
CMD_SKIP_LINE, /* keep building query */ CMD_SKIP_LINE, /* keep building query */
CMD_TERMINATE, /* quit program */ CMD_TERMINATE, /* quit program */
CMD_NEWEDIT, /* query buffer was changed (e.g., via \e) */ CMD_NEWEDIT, /* query buffer was changed (e.g., via \e) */
CMD_ERROR /* the execution of the backslash command resulted CMD_ERROR /* the execution of the backslash command
in an error */ * resulted in an error */
} backslashResult; } backslashResult;
backslashResult backslashResult HandleSlashCmds(PsqlSettings *pset,
HandleSlashCmds(PsqlSettings *pset,
const char *line, const char *line,
PQExpBuffer query_buf, PQExpBuffer query_buf,
const char ** end_of_cmd); const char **end_of_cmd);
bool bool do_connect(const char *new_dbname,
do_connect(const char *new_dbname,
const char *new_user, const char *new_user,
PsqlSettings *pset); PsqlSettings *pset);
bool bool process_file(const char *filename,
process_file(const char *filename,
PsqlSettings *pset); PsqlSettings *pset);
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);
......
...@@ -39,15 +39,19 @@ ...@@ -39,15 +39,19 @@
* "Safe" wrapper around strdup() * "Safe" wrapper around strdup()
* (Using this also avoids writing #ifdef HAVE_STRDUP in every file :) * (Using this also avoids writing #ifdef HAVE_STRDUP in every file :)
*/ */
char * xstrdup(const char * string) char *
xstrdup(const char *string)
{ {
char * tmp; char *tmp;
if (!string) {
if (!string)
{
fprintf(stderr, "xstrdup: Cannot duplicate null pointer.\n"); fprintf(stderr, "xstrdup: Cannot duplicate null pointer.\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
tmp = strdup(string); tmp = strdup(string);
if (!tmp) { if (!tmp)
{
perror("strdup"); perror("strdup");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
...@@ -72,7 +76,8 @@ setQFout(const char *fname, PsqlSettings *pset) ...@@ -72,7 +76,8 @@ setQFout(const char *fname, PsqlSettings *pset)
#ifdef USE_ASSERT_CHECKING #ifdef USE_ASSERT_CHECKING
assert(pset); assert(pset);
#else #else
if (!pset) return false; if (!pset)
return false;
#endif #endif
/* Close old file/pipe */ /* Close old file/pipe */
...@@ -85,14 +90,14 @@ setQFout(const char *fname, PsqlSettings *pset) ...@@ -85,14 +90,14 @@ setQFout(const char *fname, PsqlSettings *pset)
} }
/* If no filename, set stdout */ /* If no filename, set stdout */
if (!fname || fname[0]=='\0') if (!fname || fname[0] == '\0')
{ {
pset->queryFout = stdout; pset->queryFout = stdout;
pset->queryFoutPipe = false; pset->queryFoutPipe = false;
} }
else if (*fname == '|') else if (*fname == '|')
{ {
const char * pipename = fname+1; const char *pipename = fname + 1;
#ifndef __CYGWIN32__ #ifndef __CYGWIN32__
...@@ -147,16 +152,19 @@ char * ...@@ -147,16 +152,19 @@ char *
simple_prompt(const char *prompt, int maxlen, bool echo) simple_prompt(const char *prompt, int maxlen, bool echo)
{ {
int length; int length;
char * destination; char *destination;
#ifdef HAVE_TERMIOS_H #ifdef HAVE_TERMIOS_H
struct termios t_orig, t; struct termios t_orig,
t;
#endif #endif
destination = (char *) malloc(maxlen+2); destination = (char *) malloc(maxlen + 2);
if (!destination) if (!destination)
return NULL; return NULL;
if (prompt) fputs(prompt, stdout); if (prompt)
fputs(prompt, stdout);
#ifdef HAVE_TERMIOS_H #ifdef HAVE_TERMIOS_H
if (!echo) if (!echo)
...@@ -171,17 +179,21 @@ simple_prompt(const char *prompt, int maxlen, bool echo) ...@@ -171,17 +179,21 @@ simple_prompt(const char *prompt, int maxlen, bool echo)
fgets(destination, maxlen, stdin); fgets(destination, maxlen, stdin);
#ifdef HAVE_TERMIOS_H #ifdef HAVE_TERMIOS_H
if (!echo) { if (!echo)
{
tcsetattr(0, TCSADRAIN, &t_orig); tcsetattr(0, TCSADRAIN, &t_orig);
puts(""); puts("");
} }
#endif #endif
length = strlen(destination); length = strlen(destination);
if (length > 0 && destination[length - 1] != '\n') { if (length > 0 && destination[length - 1] != '\n')
{
/* eat rest of the line */ /* eat rest of the line */
char buf[512]; char buf[512];
do {
do
{
fgets(buf, 512, stdin); fgets(buf, 512, stdin);
} while (buf[strlen(buf) - 1] != '\n'); } while (buf[strlen(buf) - 1] != '\n');
} }
...@@ -205,18 +217,20 @@ simple_prompt(const char *prompt, int maxlen, bool echo) ...@@ -205,18 +217,20 @@ simple_prompt(const char *prompt, int maxlen, bool echo)
* immediate consumption. * immediate consumption.
*/ */
const char * const char *
interpolate_var(const char * name, PsqlSettings * pset) interpolate_var(const char *name, PsqlSettings *pset)
{ {
const char * var; const char *var;
#ifdef USE_ASSERT_CHECKING #ifdef USE_ASSERT_CHECKING
assert(name); assert(name);
assert(pset); assert(pset);
#else #else
if (!name || !pset) return NULL; if (!name || !pset)
return NULL;
#endif #endif
if (strspn(name, VALID_VARIABLE_CHARS) == strlen(name)) { if (strspn(name, VALID_VARIABLE_CHARS) == strlen(name))
{
var = GetVariable(pset->vars, name); var = GetVariable(pset->vars, name);
if (var) if (var)
return var; return var;
...@@ -225,41 +239,50 @@ interpolate_var(const char * name, PsqlSettings * pset) ...@@ -225,41 +239,50 @@ interpolate_var(const char * name, PsqlSettings * pset)
} }
/* otherwise return magic variable */ /* 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) * (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; return PG_VERSION_STR;
if (strcmp(name, "Database")==0) { if (strcmp(name, "Database") == 0)
{
if (PQdb(pset->db)) if (PQdb(pset->db))
return PQdb(pset->db); return PQdb(pset->db);
else else
return ""; return "";
} }
if (strcmp(name, "User")==0) { if (strcmp(name, "User") == 0)
{
if (PQuser(pset->db)) if (PQuser(pset->db))
return PQuser(pset->db); return PQuser(pset->db);
else else
return ""; return "";
} }
if (strcmp(name, "Host")==0) { if (strcmp(name, "Host") == 0)
{
if (PQhost(pset->db)) if (PQhost(pset->db))
return PQhost(pset->db); return PQhost(pset->db);
else else
return ""; return "";
} }
if (strcmp(name, "Port")==0) { if (strcmp(name, "Port") == 0)
{
if (PQport(pset->db)) if (PQport(pset->db))
return PQport(pset->db); return PQport(pset->db);
else else
return ""; return "";
} }
/* env vars (if env vars are all caps there should be no prob, otherwise /*
you're on your own */ * env vars (if env vars are all caps there should be no prob,
* otherwise you're on your own
*/
if ((var = getenv(name))) if ((var = getenv(name)))
return var; return var;
...@@ -284,7 +307,7 @@ interpolate_var(const char * name, PsqlSettings * pset) ...@@ -284,7 +307,7 @@ interpolate_var(const char * name, PsqlSettings * pset)
* at least avoid trusting printf by using the more primitive fputs(). * at least avoid trusting printf by using the more primitive fputs().
*/ */
PGconn * cancelConn; PGconn *cancelConn;
#ifdef WIN32 #ifdef WIN32
#define safe_write_stderr(String) fputs(s, stderr) #define safe_write_stderr(String) fputs(s, stderr)
...@@ -302,7 +325,8 @@ handle_sigint(SIGNAL_ARGS) ...@@ -302,7 +325,8 @@ handle_sigint(SIGNAL_ARGS)
/* Try to send cancel request */ /* Try to send cancel request */
if (PQrequestCancel(cancelConn)) if (PQrequestCancel(cancelConn))
safe_write_stderr("\nCANCEL request sent\n"); safe_write_stderr("\nCANCEL request sent\n");
else { else
{
safe_write_stderr("\nCould not send cancel request: "); safe_write_stderr("\nCould not send cancel request: ");
safe_write_stderr(PQerrorMessage(cancelConn)); safe_write_stderr(PQerrorMessage(cancelConn));
} }
...@@ -320,20 +344,22 @@ PGresult * ...@@ -320,20 +344,22 @@ PGresult *
PSQLexec(PsqlSettings *pset, const char *query) PSQLexec(PsqlSettings *pset, const char *query)
{ {
PGresult *res; PGresult *res;
const char * var; const char *var;
if (!pset->db) { if (!pset->db)
{
fputs("You are not currently connected to a database.\n", stderr); fputs("You are not currently connected to a database.\n", stderr);
return NULL; return NULL;
} }
var = GetVariable(pset->vars, "echo_secret"); var = GetVariable(pset->vars, "echo_secret");
if (var) { if (var)
{
printf("********* QUERY *********\n%s\n*************************\n\n", query); printf("********* QUERY *********\n%s\n*************************\n\n", query);
fflush(stdout); fflush(stdout);
} }
if (var && strcmp(var, "noexec")==0) if (var && strcmp(var, "noexec") == 0)
return NULL; return NULL;
cancelConn = pset->db; cancelConn = pset->db;
...@@ -347,7 +373,8 @@ PSQLexec(PsqlSettings *pset, const char *query) ...@@ -347,7 +373,8 @@ PSQLexec(PsqlSettings *pset, const char *query)
{ {
fputs("The connection to the server was lost. Attempting reset: ", stderr); fputs("The connection to the server was lost. Attempting reset: ", stderr);
PQreset(pset->db); PQreset(pset->db);
if (PQstatus(pset->db) == CONNECTION_BAD) { if (PQstatus(pset->db) == CONNECTION_BAD)
{
fputs("Failed.\n", stderr); fputs("Failed.\n", stderr);
PQfinish(pset->db); PQfinish(pset->db);
PQclear(res); PQclear(res);
...@@ -364,7 +391,8 @@ PSQLexec(PsqlSettings *pset, const char *query) ...@@ -364,7 +391,8 @@ PSQLexec(PsqlSettings *pset, const char *query)
PQresultStatus(res) == PGRES_COPY_OUT) PQresultStatus(res) == PGRES_COPY_OUT)
) )
return res; return res;
else { else
{
fprintf(stderr, "%s", PQerrorMessage(pset->db)); fprintf(stderr, "%s", PQerrorMessage(pset->db));
PQclear(res); PQclear(res);
return NULL; return NULL;
...@@ -392,20 +420,23 @@ SendQuery(PsqlSettings *pset, const char *query) ...@@ -392,20 +420,23 @@ SendQuery(PsqlSettings *pset, const char *query)
PGresult *results; PGresult *results;
PGnotify *notify; PGnotify *notify;
if (!pset->db) { if (!pset->db)
{
fputs("You are not currently connected to a database.\n", stderr); fputs("You are not currently connected to a database.\n", stderr);
return false; return false;
} }
if (GetVariableBool(pset->vars, "singlestep")) { if (GetVariableBool(pset->vars, "singlestep"))
{
char buf[3]; char buf[3];
fprintf(stdout, "***(Single step mode: Verify query)*********************************************\n" fprintf(stdout, "***(Single step mode: Verify query)*********************************************\n"
"QUERY: %s\n" "QUERY: %s\n"
"***(press return to proceed or enter x and return to cancel)********************\n", "***(press return to proceed or enter x and return to cancel)********************\n",
query); query);
fflush(stdout); fflush(stdout);
fgets(buf, 3, stdin); fgets(buf, 3, stdin);
if (buf[0]=='x') if (buf[0] == 'x')
return false; return false;
fflush(stdin); fflush(stdin);
} }
...@@ -432,7 +463,8 @@ SendQuery(PsqlSettings *pset, const char *query) ...@@ -432,7 +463,8 @@ SendQuery(PsqlSettings *pset, const char *query)
PsqlSettings settings_copy = *pset; PsqlSettings settings_copy = *pset;
settings_copy.queryFout = stdout; settings_copy.queryFout = stdout;
if (!setQFout(pset->gfname, &settings_copy)) { if (!setQFout(pset->gfname, &settings_copy))
{
success = false; success = false;
break; break;
} }
...@@ -491,7 +523,8 @@ SendQuery(PsqlSettings *pset, const char *query) ...@@ -491,7 +523,8 @@ SendQuery(PsqlSettings *pset, const char *query)
{ {
fputs("The connection to the server was lost. Attempting reset: ", stderr); fputs("The connection to the server was lost. Attempting reset: ", stderr);
PQreset(pset->db); PQreset(pset->db);
if (PQstatus(pset->db) == CONNECTION_BAD) { if (PQstatus(pset->db) == CONNECTION_BAD)
{
fputs("Failed.\n", stderr); fputs("Failed.\n", stderr);
PQfinish(pset->db); PQfinish(pset->db);
PQclear(results); PQclear(results);
......
...@@ -5,21 +5,21 @@ ...@@ -5,21 +5,21 @@
#include "settings.h" #include "settings.h"
char * char *
xstrdup(const char * string); xstrdup(const char *string);
bool bool
setQFout(const char *fname, PsqlSettings *pset); setQFout(const char *fname, PsqlSettings *pset);
char * char *
simple_prompt(const char *prompt, int maxlen, bool echo); simple_prompt(const char *prompt, int maxlen, bool echo);
const char * const char *
interpolate_var(const char * name, PsqlSettings * pset); interpolate_var(const char *name, PsqlSettings *pset);
PGresult * PGresult *
PSQLexec(PsqlSettings *pset, const char *query); PSQLexec(PsqlSettings *pset, const char *query);
bool bool
SendQuery(PsqlSettings *pset, const char *query); SendQuery(PsqlSettings *pset, const char *query);
#endif /* COMMON_H */ #endif /* COMMON_H */
...@@ -33,13 +33,14 @@ ...@@ -33,13 +33,14 @@
* returns a malloc'ed structure with the options, or NULL on parsing error * returns a malloc'ed structure with the options, or NULL on parsing error
*/ */
struct copy_options { struct copy_options
char * table; {
char * file; char *table;
char *file;
bool from; bool from;
bool binary; bool binary;
bool oids; bool oids;
char * delim; char *delim;
}; };
...@@ -58,15 +59,16 @@ free_copy_options(struct copy_options * ptr) ...@@ -58,15 +59,16 @@ free_copy_options(struct copy_options * ptr)
static struct copy_options * static struct copy_options *
parse_slash_copy(const char *args) parse_slash_copy(const char *args)
{ {
struct copy_options * result; struct copy_options *result;
char * line; char *line;
char * token; char *token;
bool error = false; bool error = false;
char quote; char quote;
line = xstrdup(args); line = xstrdup(args);
if (!(result = calloc(1, sizeof (struct copy_options)))) { if (!(result = calloc(1, sizeof(struct copy_options))))
{
perror("calloc"); perror("calloc");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
...@@ -74,8 +76,10 @@ parse_slash_copy(const char *args) ...@@ -74,8 +76,10 @@ parse_slash_copy(const char *args)
token = strtokx(line, " \t", "\"", '\\', &quote, NULL); token = strtokx(line, " \t", "\"", '\\', &quote, NULL);
if (!token) if (!token)
error = true; error = true;
else { else
if (!quote && strcasecmp(token, "binary")==0) { {
if (!quote && strcasecmp(token, "binary") == 0)
{
result->binary = true; result->binary = true;
token = strtokx(NULL, " \t", "\"", '\\', &quote, NULL); token = strtokx(NULL, " \t", "\"", '\\', &quote, NULL);
if (!token) if (!token)
...@@ -89,56 +93,65 @@ parse_slash_copy(const char *args) ...@@ -89,56 +93,65 @@ parse_slash_copy(const char *args)
assert(error || result->table); assert(error || result->table);
#endif #endif
if (!error) { if (!error)
{
token = strtokx(NULL, " \t", NULL, '\\', NULL, NULL); token = strtokx(NULL, " \t", NULL, '\\', NULL, NULL);
if (!token) if (!token)
error = true; error = true;
else { else
if (strcasecmp(token, "with")==0) { {
if (strcasecmp(token, "with") == 0)
{
token = strtokx(NULL, " \t", NULL, '\\', NULL, NULL); token = strtokx(NULL, " \t", NULL, '\\', NULL, NULL);
if (!token || strcasecmp(token, "oids")!=0) if (!token || strcasecmp(token, "oids") != 0)
error = true; error = true;
else else
result->oids = true; result->oids = true;
if (!error) { if (!error)
{
token = strtokx(NULL, " \t", NULL, '\\', NULL, NULL); token = strtokx(NULL, " \t", NULL, '\\', NULL, NULL);
if (!token) if (!token)
error = true; error = true;
} }
} }
if (!error && strcasecmp(token, "from")==0) if (!error && strcasecmp(token, "from") == 0)
result->from = true; result->from = true;
else if (!error && strcasecmp(token, "to")==0) else if (!error && strcasecmp(token, "to") == 0)
result->from = false; result->from = false;
else else
error = true; error = true;
} }
} }
if (!error) { if (!error)
{
token = strtokx(NULL, " \t", "'", '\\', NULL, NULL); token = strtokx(NULL, " \t", "'", '\\', NULL, NULL);
if (!token) if (!token)
error = true; error = true;
else else
result->file=xstrdup(token); result->file = xstrdup(token);
} }
#ifdef USE_ASSERT_CHECKING #ifdef USE_ASSERT_CHECKING
assert(error || result->file); assert(error || result->file);
#endif #endif
if (!error) { if (!error)
{
token = strtokx(NULL, " \t", NULL, '\\', NULL, NULL); token = strtokx(NULL, " \t", NULL, '\\', NULL, NULL);
if (token) { if (token)
if (strcasecmp(token, "using")!=0) {
if (strcasecmp(token, "using") != 0)
error = true; error = true;
else { else
{
token = strtokx(NULL, " \t", NULL, '\\', NULL, NULL); token = strtokx(NULL, " \t", NULL, '\\', NULL, NULL);
if (!token || strcasecmp(token, "delimiters")!=0) if (!token || strcasecmp(token, "delimiters") != 0)
error = true; error = true;
else { else
{
token = strtokx(NULL, " \t", "'", '\\', NULL, NULL); token = strtokx(NULL, " \t", "'", '\\', NULL, NULL);
if (token) if (token)
result->delim = xstrdup(token); result->delim = xstrdup(token);
...@@ -151,7 +164,8 @@ parse_slash_copy(const char *args) ...@@ -151,7 +164,8 @@ parse_slash_copy(const char *args)
free(line); free(line);
if (error) { if (error)
{
fputs("Parse error at ", stderr); fputs("Parse error at ", stderr);
if (!token) if (!token)
fputs("end of line.", stderr); fputs("end of line.", stderr);
...@@ -173,7 +187,7 @@ parse_slash_copy(const char *args) ...@@ -173,7 +187,7 @@ parse_slash_copy(const char *args)
* 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, PsqlSettings *pset)
{ {
char query[128 + NAMEDATALEN]; char query[128 + NAMEDATALEN];
FILE *copystream; FILE *copystream;
...@@ -204,10 +218,14 @@ do_copy(const char * args, PsqlSettings *pset) ...@@ -204,10 +218,14 @@ do_copy(const char * args, PsqlSettings *pset)
strcat(query, "TO stdout"); strcat(query, "TO stdout");
if (options->delim) { if (options->delim)
/* backend copy only uses the first character here, {
but that might be the escape backslash
(makes me wonder though why it's called delimiterS) */ /*
* backend copy only uses the first character here, but that might
* be the escape backslash (makes me wonder though why it's called
* delimiterS)
*/
strncat(query, " USING DELIMITERS '", 2); strncat(query, " USING DELIMITERS '", 2);
strcat(query, options->delim); strcat(query, options->delim);
strcat(query, "'"); strcat(query, "'");
...@@ -227,7 +245,8 @@ do_copy(const char * args, PsqlSettings *pset) ...@@ -227,7 +245,8 @@ do_copy(const char * args, PsqlSettings *pset)
copystream = fopen(options->file, "wb"); copystream = fopen(options->file, "wb");
#endif #endif
if (!copystream) { if (!copystream)
{
fprintf(stderr, fprintf(stderr,
"Unable to open file %s which to copy: %s\n", "Unable to open file %s which to copy: %s\n",
options->from ? "from" : "to", strerror(errno)); options->from ? "from" : "to", strerror(errno));
...@@ -258,7 +277,8 @@ do_copy(const char * args, PsqlSettings *pset) ...@@ -258,7 +277,8 @@ do_copy(const char * args, PsqlSettings *pset)
PQclear(result); PQclear(result);
if (!GetVariable(pset->vars, "quiet")) { if (!GetVariable(pset->vars, "quiet"))
{
if (success) if (success)
puts("Successfully copied."); puts("Successfully copied.");
else else
...@@ -337,7 +357,7 @@ handleCopyOut(PGconn *conn, FILE *copystream) ...@@ -337,7 +357,7 @@ handleCopyOut(PGconn *conn, FILE *copystream)
*/ */
bool bool
handleCopyIn(PGconn *conn, FILE *copystream, const char * prompt) handleCopyIn(PGconn *conn, FILE *copystream, const char *prompt)
{ {
bool copydone = false; bool copydone = false;
bool firstload; bool firstload;
......
...@@ -8,15 +8,15 @@ ...@@ -8,15 +8,15 @@
/* handler for \copy */ /* handler for \copy */
bool bool
do_copy(const char *args, PsqlSettings *pset); do_copy(const char *args, PsqlSettings *pset);
/* lower level processors for copy in/out streams */ /* lower level processors for copy in/out streams */
bool bool
handleCopyOut(PGconn *conn, FILE *copystream); handleCopyOut(PGconn *conn, FILE *copystream);
bool bool
handleCopyIn(PGconn *conn, FILE *copystream, const char * prompt); handleCopyIn(PGconn *conn, FILE *copystream, const char *prompt);
#endif #endif
This diff is collapsed.
...@@ -5,38 +5,38 @@ ...@@ -5,38 +5,38 @@
/* \da */ /* \da */
bool bool
describeAggregates(const char * name, PsqlSettings * pset); describeAggregates(const char *name, PsqlSettings *pset);
/* \df */ /* \df */
bool bool
describeFunctions(const char * name, PsqlSettings * pset); describeFunctions(const char *name, PsqlSettings *pset);
/* \dT */ /* \dT */
bool bool
describeTypes(const char * name, PsqlSettings * pset); describeTypes(const char *name, PsqlSettings *pset);
/* \do */ /* \do */
bool bool
describeOperators(const char * name, PsqlSettings * pset); describeOperators(const char *name, PsqlSettings *pset);
/* \dp (formerly \z) */ /* \dp (formerly \z) */
bool bool
permissionsList(const char * name, PsqlSettings *pset); permissionsList(const char *name, PsqlSettings *pset);
/* \dd */ /* \dd */
bool bool
objectDescription(const char * object, PsqlSettings *pset); objectDescription(const char *object, PsqlSettings *pset);
/* \d foo */ /* \d foo */
bool bool
describeTableDetails(const char * name, PsqlSettings * pset); describeTableDetails(const char *name, PsqlSettings *pset);
/* \l */ /* \l */
bool bool
listAllDbs(PsqlSettings *pset); listAllDbs(PsqlSettings *pset);
/* \dt, \di, \dS, etc. */ /* \dt, \di, \dS, etc. */
bool bool
listTables(const char * infotype, const char * name, PsqlSettings * pset); listTables(const char *infotype, const char *name, PsqlSettings *pset);
#endif /* DESCRIBE_H */ #endif /* DESCRIBE_H */
...@@ -34,21 +34,27 @@ ...@@ -34,21 +34,27 @@
*/ */
#define ON(var) (var ? "on" : "off") #define ON(var) (var ? "on" : "off")
void usage(void) void
usage(void)
{ {
const char *env; const char *env;
const char *user; const char *user;
#ifndef WIN32 #ifndef WIN32
struct passwd *pw = NULL; struct passwd *pw = NULL;
#endif #endif
/* Find default user, in case we need it. */ /* Find default user, in case we need it. */
user = getenv("USER"); user = getenv("USER");
if (!user) { if (!user)
{
#ifndef WIN32 #ifndef WIN32
pw = getpwuid(getuid()); pw = getpwuid(getuid());
if (pw) user = pw->pw_name; if (pw)
else { user = pw->pw_name;
else
{
perror("getpwuid()"); perror("getpwuid()");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
...@@ -64,7 +70,8 @@ void usage(void) ...@@ -64,7 +70,8 @@ void usage(void)
/* Display default database */ /* Display default database */
env = getenv("PGDATABASE"); env = getenv("PGDATABASE");
if (!env) env=user; if (!env)
env = user;
fprintf(stderr, " -d dbname Specify database name to connect to (default: %s)\n", env); fprintf(stderr, " -d dbname Specify database name to connect to (default: %s)\n", env);
fprintf(stderr, " -e Echo all input in non-interactive mode\n"); fprintf(stderr, " -e Echo all input in non-interactive mode\n");
...@@ -101,7 +108,8 @@ void usage(void) ...@@ -101,7 +108,8 @@ void usage(void)
/* Display default user */ /* Display default user */
env = getenv("PGUSER"); env = getenv("PGUSER");
if (!env) env=user; if (!env)
env = user;
fprintf(stderr, " -U [username] Specifiy username, \"?\"=prompt (default user: %s)\n", env); fprintf(stderr, " -U [username] Specifiy username, \"?\"=prompt (default user: %s)\n", env);
fprintf(stderr, " -x Turn on expanded table output (-P expanded)\n"); fprintf(stderr, " -x Turn on expanded table output (-P expanded)\n");
...@@ -112,7 +120,8 @@ void usage(void) ...@@ -112,7 +120,8 @@ void usage(void)
fprintf(stderr, "Consult the documentation for the complete details.\n"); fprintf(stderr, "Consult the documentation for the complete details.\n");
#ifndef WIN32 #ifndef WIN32
if (pw) free(pw); if (pw)
free(pw);
#endif #endif
} }
...@@ -125,10 +134,12 @@ void usage(void) ...@@ -125,10 +134,12 @@ void usage(void)
*/ */
#ifndef TIOCGWINSZ #ifndef TIOCGWINSZ
struct winsize { struct winsize
{
int ws_row; int ws_row;
int ws_col; int ws_col;
}; };
#endif #endif
void void
...@@ -197,7 +208,8 @@ slashUsage(PsqlSettings *pset) ...@@ -197,7 +208,8 @@ slashUsage(PsqlSettings *pset)
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");
if (usePipe) { if (usePipe)
{
pclose(fout); pclose(fout);
pqsignal(SIGPIPE, SIG_DFL); pqsignal(SIGPIPE, SIG_DFL);
} }
...@@ -212,7 +224,7 @@ slashUsage(PsqlSettings *pset) ...@@ -212,7 +224,7 @@ slashUsage(PsqlSettings *pset)
void void
helpSQL(const char *topic) helpSQL(const char *topic)
{ {
if (!topic || strlen(topic)==0) if (!topic || strlen(topic) == 0)
{ {
char left_center_right; /* Which column we're displaying */ char left_center_right; /* Which column we're displaying */
int i; /* Index into QL_HELP[] */ int i; /* Index into QL_HELP[] */
...@@ -274,33 +286,33 @@ void ...@@ -274,33 +286,33 @@ void
print_copyright(void) print_copyright(void)
{ {
puts( puts(
" "
PostgreSQL Data Base Management System PostgreSQL Data Base Management System
Copyright (c) 1996-9 PostgreSQL Global Development Group Copyright(c) 1996 - 9 PostgreSQL Global Development Group
This software is based on Postgres95, formerly known as Postgres, which This software is based on Postgres95, formerly known as Postgres, which
contains the following notice: contains the following notice:
Copyright (c) 1994-7 Regents of the University of California Copyright(c) 1994 - 7 Regents of the University of California
Permission to use, copy, modify, and distribute this software and its Permission to use, copy, modify, and distribute this software and its
documentation for any purpose, without fee, and without a written agreement documentation for any purpose, without fee, and without a written agreement
is hereby granted, provided that the above copyright notice and this paragraph is hereby granted, provided that the above copyright notice and this paragraph
and the following two paragraphs appear in all copies. and the following two paragraphs appear in all copies.
IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST
PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE. DAMAGE.
THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN \"AS IS\" BASIS, PARTICULAR PURPOSE.THE SOFTWARE PROVIDED HEREUNDER IS ON AN \ "AS IS\" BASIS,
AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE,
SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
(end of terms)" (end of terms) "
); );
} }
...@@ -13,4 +13,3 @@ void print_copyright(void); ...@@ -13,4 +13,3 @@ void print_copyright(void);
#endif #endif
...@@ -10,9 +10,11 @@ ...@@ -10,9 +10,11 @@
/* (of course there is no runtime command for doing that :) */ /* (of course there is no runtime command for doing that :) */
#ifdef USE_READLINE #ifdef USE_READLINE
static bool useReadline; static bool useReadline;
#endif #endif
#ifdef USE_HISTORY #ifdef USE_HISTORY
static bool useHistory; static bool useHistory;
#endif #endif
...@@ -25,15 +27,17 @@ static bool useHistory; ...@@ -25,15 +27,17 @@ static bool useHistory;
char * char *
gets_interactive(const char *prompt) gets_interactive(const char *prompt)
{ {
char * s; char *s;
#ifdef USE_READLINE #ifdef USE_READLINE
if (useReadline) { if (useReadline)
{
s = readline(prompt); s = readline(prompt);
fputc('\r', stdout); fputc('\r', stdout);
fflush(stdout); fflush(stdout);
} }
else { else
{
#endif #endif
fputs(prompt, stdout); fputs(prompt, stdout);
fflush(stdout); fflush(stdout);
...@@ -65,10 +69,12 @@ gets_fromFile(FILE *source) ...@@ -65,10 +69,12 @@ gets_fromFile(FILE *source)
initPQExpBuffer(&buffer); initPQExpBuffer(&buffer);
while (fgets(line, 1024, source) != NULL) { while (fgets(line, 1024, source) != NULL)
{
appendPQExpBufferStr(&buffer, line); appendPQExpBufferStr(&buffer, line);
if (buffer.data[buffer.len-1] == '\n') { if (buffer.data[buffer.len - 1] == '\n')
buffer.data[buffer.len-1] = '\0'; {
buffer.data[buffer.len - 1] = '\0';
return buffer.data; return buffer.data;
} }
} }
...@@ -93,22 +99,27 @@ void ...@@ -93,22 +99,27 @@ void
initializeInput(int flags) 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";
} }
#endif #endif
#ifdef USE_HISTORY #ifdef USE_HISTORY
if (flags == 1) { if (flags == 1)
const char * home; {
const char *home;
useHistory = true; useHistory = true;
using_history(); using_history();
home = getenv("HOME"); home = getenv("HOME");
if (home) { if (home)
char * psql_history = (char *) malloc(strlen(home) + 20); {
if (psql_history) { char *psql_history = (char *) malloc(strlen(home) + 20);
if (psql_history)
{
sprintf(psql_history, "%s/.psql_history", home); sprintf(psql_history, "%s/.psql_history", home);
read_history(psql_history); read_history(psql_history);
free(psql_history); free(psql_history);
...@@ -124,8 +135,10 @@ bool ...@@ -124,8 +135,10 @@ bool
saveHistory(const char *fname) saveHistory(const char *fname)
{ {
#ifdef USE_HISTORY #ifdef USE_HISTORY
if (useHistory) { if (useHistory)
if (write_history(fname) != 0) { {
if (write_history(fname) != 0)
{
perror(fname); perror(fname);
return false; return false;
} }
...@@ -144,14 +157,17 @@ void ...@@ -144,14 +157,17 @@ void
finishInput(void) finishInput(void)
{ {
#ifdef USE_HISTORY #ifdef USE_HISTORY
if (useHistory) { if (useHistory)
char * home; {
char * psql_history; char *home;
char *psql_history;
home = getenv("HOME"); home = getenv("HOME");
if (home) { if (home)
{
psql_history = (char *) malloc(strlen(home) + 20); psql_history = (char *) malloc(strlen(home) + 20);
if (psql_history) { if (psql_history)
{
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);
......
...@@ -38,19 +38,19 @@ ...@@ -38,19 +38,19 @@
char * char *
gets_interactive(const char *prompt); gets_interactive(const char *prompt);
char * char *
gets_fromFile(FILE *source); gets_fromFile(FILE *source);
void void
initializeInput(int flags); initializeInput(int flags);
bool bool
saveHistory(const char *fname); saveHistory(const char *fname);
void void
finishInput(void); finishInput(void);
#endif #endif
...@@ -24,25 +24,26 @@ ...@@ -24,25 +24,26 @@
static char notice[80]; static char notice[80];
static void static void
_my_notice_handler(void * arg, const char * message) { _my_notice_handler(void *arg, const char *message)
(void)arg; {
(void) arg;
strncpy(notice, message, 79); strncpy(notice, message, 79);
notice[79] = '\0'; notice[79] = '\0';
} }
static bool static bool
handle_transaction(PsqlSettings * pset) handle_transaction(PsqlSettings *pset)
{ {
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;
if (var && strcmp(var, "nothing")==0) if (var && strcmp(var, "nothing") == 0)
return true; return true;
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);
...@@ -51,12 +52,14 @@ handle_transaction(PsqlSettings * pset) ...@@ -51,12 +52,14 @@ handle_transaction(PsqlSettings * pset)
if (!res) if (!res)
return false; return false;
if (notice[0]) { if (notice[0])
if ( (!commit && strcmp(notice, "NOTICE: UserAbortTransactionBlock and not in in-progress state\n")!=0) || {
(commit && strcmp(notice, "NOTICE: EndTransactionBlock and not inprogress/abort state\n")!=0) ) if ((!commit && strcmp(notice, "NOTICE: UserAbortTransactionBlock and not in in-progress 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 (!GetVariableBool(pset->vars, "quiet"))
{
if (commit) if (commit)
puts("Warning: Your transaction in progress has been committed."); puts("Warning: Your transaction in progress has been committed.");
else else
...@@ -75,22 +78,24 @@ handle_transaction(PsqlSettings * pset) ...@@ -75,22 +78,24 @@ 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(PsqlSettings *pset, 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)
{
fputs("You are not connected to a database.\n", stderr); fputs("You are not connected to a database.\n", stderr);
return false; return false;
} }
if (own_transaction) { if (own_transaction)
{
if (!handle_transaction(pset)) if (!handle_transaction(pset))
return false; return false;
...@@ -100,18 +105,23 @@ do_lo_export(PsqlSettings * pset, const char * loid_arg, const char * filename_a ...@@ -100,18 +105,23 @@ do_lo_export(PsqlSettings * pset, const char * loid_arg, const char * filename_a
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) { /* of course this status is documented nowhere :( */ if (status != 1)
{ /* of course this status is documented
* 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;
} }
if (own_transaction) { if (own_transaction)
if (!(res = PSQLexec(pset, "COMMIT"))) { {
if (!(res = PSQLexec(pset, "COMMIT")))
{
res = PQexec(pset->db, "ROLLBACK"); res = PQexec(pset->db, "ROLLBACK");
PQclear(res); PQclear(res);
return false; return false;
...@@ -133,24 +143,26 @@ do_lo_export(PsqlSettings * pset, const char * loid_arg, const char * filename_a ...@@ -133,24 +143,26 @@ do_lo_export(PsqlSettings * pset, const char * loid_arg, const char * filename_a
* 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(PsqlSettings *pset, 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)
{
fputs("You are not connected to a database.\n", stderr); fputs("You are not connected to a database.\n", stderr);
return false; return false;
} }
if (own_transaction) { if (own_transaction)
{
if (!handle_transaction(pset)) if (!handle_transaction(pset))
return false; return false;
...@@ -160,10 +172,12 @@ do_lo_import(PsqlSettings * pset, const char * filename_arg, const char * commen ...@@ -160,10 +172,12 @@ do_lo_import(PsqlSettings * pset, const char * filename_arg, const char * commen
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);
} }
...@@ -171,17 +185,20 @@ do_lo_import(PsqlSettings * pset, const char * filename_arg, const char * commen ...@@ -171,17 +185,20 @@ do_lo_import(PsqlSettings * pset, const char * filename_arg, const char * commen
} }
/* insert description if given */ /* insert description if given */
if (comment_arg) { if (comment_arg)
{
sprintf(buf, "INSERT INTO pg_description VALUES (%d, '", loid); sprintf(buf, "INSERT INTO pg_description VALUES (%d, '", loid);
for (i=0; i<strlen(comment_arg); i++) for (i = 0; i < strlen(comment_arg); i++)
if (comment_arg[i]=='\'') if (comment_arg[i] == '\'')
strcat(buf, "\\'"); strcat(buf, "\\'");
else else
strncat(buf, &comment_arg[i], 1); strncat(buf, &comment_arg[i], 1);
strcat(buf, "')"); strcat(buf, "')");
if (!(res = PSQLexec(pset, buf))) { if (!(res = PSQLexec(pset, buf)))
if (own_transaction) { {
if (own_transaction)
{
res = PQexec(pset->db, "ROLLBACK"); res = PQexec(pset->db, "ROLLBACK");
PQclear(res); PQclear(res);
} }
...@@ -189,8 +206,10 @@ do_lo_import(PsqlSettings * pset, const char * filename_arg, const char * commen ...@@ -189,8 +206,10 @@ do_lo_import(PsqlSettings * pset, const char * filename_arg, const char * commen
} }
} }
if (own_transaction) { if (own_transaction)
if (!(res = PSQLexec(pset, "COMMIT"))) { {
if (!(res = PSQLexec(pset, "COMMIT")))
{
res = PQexec(pset->db, "ROLLBACK"); res = PQexec(pset->db, "ROLLBACK");
PQclear(res); PQclear(res);
return false; return false;
...@@ -212,24 +231,27 @@ do_lo_import(PsqlSettings * pset, const char * filename_arg, const char * commen ...@@ -212,24 +231,27 @@ do_lo_import(PsqlSettings * pset, const char * filename_arg, const char * commen
* *
* removes a large object out of the database * removes a large object out of the database
*/ */
bool do_lo_unlink(PsqlSettings * pset, const char * loid_arg) bool
do_lo_unlink(PsqlSettings *pset, 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)
{
fputs("You are not connected to a database.\n", stderr); fputs("You are not connected to a database.\n", stderr);
return false; return false;
} }
if (own_transaction) { if (own_transaction)
{
if (!handle_transaction(pset)) if (!handle_transaction(pset))
return false; return false;
...@@ -240,9 +262,11 @@ bool do_lo_unlink(PsqlSettings * pset, const char * loid_arg) ...@@ -240,9 +262,11 @@ bool do_lo_unlink(PsqlSettings * pset, const char * loid_arg)
} }
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);
} }
...@@ -251,8 +275,10 @@ bool do_lo_unlink(PsqlSettings * pset, const char * loid_arg) ...@@ -251,8 +275,10 @@ bool 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(pset, buf)))
if (own_transaction) { {
if (own_transaction)
{
res = PQexec(pset->db, "ROLLBACK"); res = PQexec(pset->db, "ROLLBACK");
PQclear(res); PQclear(res);
} }
...@@ -260,8 +286,10 @@ bool do_lo_unlink(PsqlSettings * pset, const char * loid_arg) ...@@ -260,8 +286,10 @@ bool do_lo_unlink(PsqlSettings * pset, const char * loid_arg)
} }
if (own_transaction) { if (own_transaction)
if (!(res = PSQLexec(pset, "COMMIT"))) { {
if (!(res = PSQLexec(pset, "COMMIT")))
{
res = PQexec(pset->db, "ROLLBACK"); res = PQexec(pset->db, "ROLLBACK");
PQclear(res); PQclear(res);
return false; return false;
...@@ -282,9 +310,10 @@ bool do_lo_unlink(PsqlSettings * pset, const char * loid_arg) ...@@ -282,9 +310,10 @@ bool do_lo_unlink(PsqlSettings * pset, const char * loid_arg)
* *
* Show all large objects in database, with comments if desired * Show all large objects in database, with comments if desired
*/ */
bool do_lo_list(PsqlSettings * pset) bool
do_lo_list(PsqlSettings *pset)
{ {
PGresult * res; PGresult *res;
char descbuf[512]; char descbuf[512];
printQueryOpt myopt = pset->popt; printQueryOpt myopt = pset->popt;
...@@ -292,7 +321,7 @@ bool do_lo_list(PsqlSettings * pset) ...@@ -292,7 +321,7 @@ bool do_lo_list(PsqlSettings * pset)
strcat(descbuf, "SELECT usename as \"Owner\", substring(relname from 5) as \"ID\""); strcat(descbuf, "SELECT usename as \"Owner\", substring(relname from 5) as \"ID\"");
if (GetVariableBool(pset->vars, "description")) if (GetVariableBool(pset->vars, "description"))
strcat(descbuf, ",\n obj_description(pg_class.oid) as \"Description\""); strcat(descbuf, ",\n obj_description(pg_class.oid) as \"Description\"");
strcat(descbuf,"\nFROM pg_class, pg_user\n" strcat(descbuf, "\nFROM pg_class, pg_user\n"
"WHERE usesysid = relowner AND relkind = 'l'\n" "WHERE usesysid = relowner AND relkind = 'l'\n"
"ORDER BY \"ID\""); "ORDER BY \"ID\"");
......
...@@ -3,9 +3,9 @@ ...@@ -3,9 +3,9 @@
#include "settings.h" #include "settings.h"
bool do_lo_export(PsqlSettings * pset, const char * loid_arg, const char * filename_arg); 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_import(PsqlSettings *pset, const char *filename_arg, const char *comment_arg);
bool do_lo_unlink(PsqlSettings * pset, const char * loid_arg); bool do_lo_unlink(PsqlSettings *pset, const char *loid_arg);
bool do_lo_list(PsqlSettings * pset); bool do_lo_list(PsqlSettings *pset);
#endif /* LARGE_OBJ_H */ #endif /* LARGE_OBJ_H */
...@@ -40,7 +40,9 @@ MainLoop(PsqlSettings *pset, FILE *source) ...@@ -40,7 +40,9 @@ MainLoop(PsqlSettings *pset, FILE *source)
int paren_level; int paren_level;
unsigned int query_start; unsigned int query_start;
int i, prevlen, thislen; int i,
prevlen,
thislen;
/* Save the prior command source */ /* Save the prior command source */
FILE *prev_cmd_source; FILE *prev_cmd_source;
...@@ -60,7 +62,8 @@ MainLoop(PsqlSettings *pset, FILE *source) ...@@ -60,7 +62,8 @@ MainLoop(PsqlSettings *pset, FILE *source)
query_buf = createPQExpBuffer(); query_buf = createPQExpBuffer();
if (!query_buf) { if (!query_buf)
{
perror("createPQExpBuffer"); perror("createPQExpBuffer");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
...@@ -76,6 +79,7 @@ MainLoop(PsqlSettings *pset, FILE *source) ...@@ -76,6 +79,7 @@ MainLoop(PsqlSettings *pset, FILE *source)
{ {
if (slashCmdStatus == CMD_NEWEDIT) if (slashCmdStatus == CMD_NEWEDIT)
{ {
/* /*
* just returned from editing the line? then just copy to the * just returned from editing the line? then just copy to the
* input buffer * input buffer
...@@ -89,9 +93,10 @@ MainLoop(PsqlSettings *pset, FILE *source) ...@@ -89,9 +93,10 @@ MainLoop(PsqlSettings *pset, FILE *source)
} }
else else
{ {
/* /*
* otherwise, set interactive prompt if necessary * otherwise, set interactive prompt if necessary and get
* and get another line * another line
*/ */
if (pset->cur_cmd_interactive) if (pset->cur_cmd_interactive)
{ {
...@@ -100,7 +105,7 @@ MainLoop(PsqlSettings *pset, FILE *source) ...@@ -100,7 +105,7 @@ MainLoop(PsqlSettings *pset, FILE *source)
if (in_quote && in_quote == '\'') if (in_quote && in_quote == '\'')
prompt_status = PROMPT_SINGLEQUOTE; prompt_status = PROMPT_SINGLEQUOTE;
else if (in_quote && in_quote == '"') else if (in_quote && in_quote == '"')
prompt_status= PROMPT_DOUBLEQUOTE; prompt_status = PROMPT_DOUBLEQUOTE;
else if (xcomment != NULL) else if (xcomment != NULL)
prompt_status = PROMPT_COMMENT; prompt_status = PROMPT_COMMENT;
else if (query_buf->len > 0) else if (query_buf->len > 0)
...@@ -121,9 +126,10 @@ MainLoop(PsqlSettings *pset, FILE *source) ...@@ -121,9 +126,10 @@ MainLoop(PsqlSettings *pset, FILE *source)
/* /*
* query_buf holds query already accumulated. line is the malloc'd * query_buf holds query already accumulated. line is the
* new line of input (note it must be freed before looping around!) * malloc'd new line of input (note it must be freed before
* query_start is the next command start location within the line. * looping around!) query_start is the next command start location
* within the line.
*/ */
/* No more input. Time to quit, or \i done */ /* No more input. Time to quit, or \i done */
...@@ -141,8 +147,10 @@ MainLoop(PsqlSettings *pset, FILE *source) ...@@ -141,8 +147,10 @@ MainLoop(PsqlSettings *pset, FILE *source)
/* strip trailing backslashes, they don't have a clear meaning */ /* strip trailing backslashes, they don't have a clear meaning */
while (1) { while (1)
char * cp = strrchr(line, '\\'); {
char *cp = strrchr(line, '\\');
if (cp && (*(cp + 1) == '\0')) if (cp && (*(cp + 1) == '\0'))
*cp = '\0'; *cp = '\0';
else else
...@@ -159,21 +167,26 @@ MainLoop(PsqlSettings *pset, FILE *source) ...@@ -159,21 +167,26 @@ MainLoop(PsqlSettings *pset, FILE *source)
len = strlen(line); len = strlen(line);
thislen = PQmblen(line); thislen = PQmblen(line);
for (i = 0; line[i]; i += (thislen = PQmblen(&line[i])) ) { for (i = 0; line[i]; i += (thislen = PQmblen(&line[i])))
if (interpol_char && interpol_char[0] != '\0' && interpol_char[0] == line[i]) { {
size_t in_length, out_length; if (interpol_char && interpol_char[0] != '\0' && interpol_char[0] == line[i])
const char * value; {
char * new; size_t in_length,
bool closer; /* did we have a closing delimiter or just an end of line? */ out_length;
const char *value;
in_length = strcspn(&line[i+thislen], interpol_char); char *new;
bool closer; /* did we have a closing delimiter
* or just an end of line? */
in_length = strcspn(&line[i + thislen], interpol_char);
closer = line[i + thislen + in_length] == line[i]; closer = line[i + thislen + in_length] == line[i];
line[i + thislen + in_length] = '\0'; line[i + thislen + in_length] = '\0';
value = interpolate_var(&line[i + thislen], pset); value = interpolate_var(&line[i + thislen], pset);
out_length = strlen(value); out_length = strlen(value);
new = malloc(len + out_length - (in_length + (closer ? 2 : 1)) + 1); new = malloc(len + out_length - (in_length + (closer ? 2 : 1)) + 1);
if (!new) { if (!new)
{
perror("malloc"); perror("malloc");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
...@@ -191,7 +204,8 @@ MainLoop(PsqlSettings *pset, FILE *source) ...@@ -191,7 +204,8 @@ MainLoop(PsqlSettings *pset, FILE *source)
} }
/* nothing left on line? then ignore */ /* nothing left on line? then ignore */
if (line[0] == '\0') { if (line[0] == '\0')
{
free(line); free(line);
continue; continue;
} }
...@@ -204,8 +218,8 @@ MainLoop(PsqlSettings *pset, FILE *source) ...@@ -204,8 +218,8 @@ MainLoop(PsqlSettings *pset, FILE *source)
/* /*
* Parse line, looking for command separators. * Parse line, looking for command separators.
* *
* The current character is at line[i], the prior character at * The current character is at line[i], the prior character at line[i
* line[i - prevlen], the next character at line[i + thislen]. * - prevlen], the next character at line[i + thislen].
*/ */
prevlen = 0; prevlen = 0;
thislen = (len > 0) ? PQmblen(line) : 0; thislen = (len > 0) ? PQmblen(line) : 0;
...@@ -213,7 +227,8 @@ MainLoop(PsqlSettings *pset, FILE *source) ...@@ -213,7 +227,8 @@ MainLoop(PsqlSettings *pset, FILE *source)
#define ADVANCE_1 (prevlen = thislen, i += thislen, thislen = PQmblen(line+i)) #define ADVANCE_1 (prevlen = thislen, i += thislen, thislen = PQmblen(line+i))
success = true; success = true;
for (i = 0; i < len; ADVANCE_1) { for (i = 0; i < len; ADVANCE_1)
{
if (!success && die_on_error) if (!success && die_on_error)
break; break;
...@@ -226,7 +241,8 @@ MainLoop(PsqlSettings *pset, FILE *source) ...@@ -226,7 +241,8 @@ MainLoop(PsqlSettings *pset, FILE *source)
/* in quote? */ /* in quote? */
if (in_quote) { if (in_quote)
{
/* end of quote */ /* end of quote */
if (line[i] == in_quote && !was_bslash) if (line[i] == in_quote && !was_bslash)
in_quote = '\0'; in_quote = '\0';
...@@ -237,15 +253,18 @@ MainLoop(PsqlSettings *pset, FILE *source) ...@@ -237,15 +253,18 @@ MainLoop(PsqlSettings *pset, FILE *source)
in_quote = line[i]; in_quote = line[i];
/* in extended comment? */ /* in extended comment? */
else if (xcomment != NULL) { else if (xcomment != NULL)
if (line[i] == '*' && line[i + thislen] == '/') { {
if (line[i] == '*' && line[i + thislen] == '/')
{
xcomment = NULL; xcomment = NULL;
ADVANCE_1; ADVANCE_1;
} }
} }
/* start of extended comment? */ /* start of extended comment? */
else if (line[i] == '/' && line[i + thislen] == '*') { else if (line[i] == '/' && line[i + thislen] == '*')
{
xcomment = &line[i]; xcomment = &line[i];
ADVANCE_1; ADVANCE_1;
} }
...@@ -266,11 +285,17 @@ MainLoop(PsqlSettings *pset, FILE *source) ...@@ -266,11 +285,17 @@ MainLoop(PsqlSettings *pset, FILE *source)
paren_level--; paren_level--;
/* semicolon? then send query */ /* semicolon? then send query */
else if (line[i] == ';' && !was_bslash && paren_level==0) { else if (line[i] == ';' && !was_bslash && paren_level == 0)
{
line[i] = '\0'; line[i] = '\0';
/* is there anything else on the line? */ /* is there anything else on the line? */
if (line[query_start + strspn(line + query_start, " \t")]!='\0') { if (line[query_start + strspn(line + query_start, " \t")] != '\0')
/* insert a cosmetic newline, if this is not the first line in the buffer */ {
/*
* insert a cosmetic newline, if this is not the first
* line in the buffer
*/
if (query_buf->len > 0) if (query_buf->len > 0)
appendPQExpBufferChar(query_buf, '\n'); appendPQExpBufferChar(query_buf, '\n');
/* append the line to the query buffer */ /* append the line to the query buffer */
...@@ -285,14 +310,20 @@ MainLoop(PsqlSettings *pset, FILE *source) ...@@ -285,14 +310,20 @@ MainLoop(PsqlSettings *pset, FILE *source)
} }
/* backslash command */ /* backslash command */
else if (was_bslash) { else if (was_bslash)
const char * end_of_cmd = NULL; {
const char *end_of_cmd = NULL;
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? */
if (line[query_start + strspn(line + query_start, " \t")]!='\0') { if (line[query_start + strspn(line + query_start, " \t")] != '\0')
/* insert a cosmetic newline, if this is not the first line in the buffer */ {
/*
* insert a cosmetic newline, if this is not the first
* line in the buffer
*/
if (query_buf->len > 0) if (query_buf->len > 0)
appendPQExpBufferChar(query_buf, '\n'); appendPQExpBufferChar(query_buf, '\n');
/* append the line to the query buffer */ /* append the line to the query buffer */
...@@ -305,14 +336,16 @@ MainLoop(PsqlSettings *pset, FILE *source) ...@@ -305,14 +336,16 @@ MainLoop(PsqlSettings *pset, FILE *source)
success = slashCmdStatus != CMD_ERROR; success = slashCmdStatus != CMD_ERROR;
if (slashCmdStatus == CMD_SEND) { if (slashCmdStatus == CMD_SEND)
{
success = SendQuery(pset, query_buf->data); success = SendQuery(pset, query_buf->data);
resetPQExpBuffer(query_buf); resetPQExpBuffer(query_buf);
query_start = i + thislen; query_start = i + thislen;
} }
/* is there anything left after the backslash command? */ /* is there anything left after the backslash command? */
if (end_of_cmd) { if (end_of_cmd)
{
i += end_of_cmd - &line[i]; i += end_of_cmd - &line[i];
query_start = i; query_start = i;
} }
...@@ -322,20 +355,23 @@ MainLoop(PsqlSettings *pset, FILE *source) ...@@ -322,20 +355,23 @@ 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;
} }
if (slashCmdStatus == CMD_TERMINATE) { if (slashCmdStatus == CMD_TERMINATE)
{
successResult = EXIT_SUCCESS; successResult = EXIT_SUCCESS;
break; break;
} }
/* Put the rest of the line in the query buffer. */ /* Put the rest of the line in the query buffer. */
if (line[query_start + strspn(line + query_start, " \t")]!='\0') { if (line[query_start + strspn(line + query_start, " \t")] != '\0')
{
if (query_buf->len > 0) if (query_buf->len > 0)
appendPQExpBufferChar(query_buf, '\n'); appendPQExpBufferChar(query_buf, '\n');
appendPQExpBufferStr(query_buf, line + query_start); appendPQExpBufferStr(query_buf, line + query_start);
...@@ -345,14 +381,16 @@ MainLoop(PsqlSettings *pset, FILE *source) ...@@ -345,14 +381,16 @@ 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(pset, query_buf->data);
resetPQExpBuffer(query_buf); resetPQExpBuffer(query_buf);
} }
/* 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;
} }
...@@ -365,4 +403,3 @@ MainLoop(PsqlSettings *pset, FILE *source) ...@@ -365,4 +403,3 @@ MainLoop(PsqlSettings *pset, FILE *source)
return successResult; return successResult;
} /* MainLoop() */ } /* MainLoop() */
...@@ -5,6 +5,6 @@ ...@@ -5,6 +5,6 @@
#include "settings.h" #include "settings.h"
int int
MainLoop(PsqlSettings *pset, FILE *source); MainLoop(PsqlSettings *pset, FILE *source);
#endif MAINLOOP_H #endif /* MAINLOOP_H */
This diff is collapsed.
...@@ -7,7 +7,8 @@ ...@@ -7,7 +7,8 @@
#include <stdio.h> #include <stdio.h>
#include <libpq-fe.h> #include <libpq-fe.h>
enum printFormat { enum printFormat
{
PRINT_NOTHING = 0, /* to make sure someone initializes this */ PRINT_NOTHING = 0, /* to make sure someone initializes this */
PRINT_UNALIGNED, PRINT_UNALIGNED,
PRINT_ALIGNED, PRINT_ALIGNED,
...@@ -17,12 +18,16 @@ enum printFormat { ...@@ -17,12 +18,16 @@ enum printFormat {
}; };
typedef struct _printTableOpt { typedef struct _printTableOpt
{
enum printFormat format; /* one of the above */ enum printFormat format; /* one of the above */
bool expanded; /* expanded/vertical output (if supported by output format) */ bool expanded; /* expanded/vertical output (if supported
bool pager; /* use pager for output (if to stdout and stdout is a tty) */ * by output format) */
bool pager; /* use pager for output (if to stdout and
* stdout is a tty) */
bool tuples_only; /* don't output headers, row counts, etc. */ bool tuples_only; /* don't output headers, row counts, etc. */
unsigned short int border; /* Print a border around the table. 0=none, 1=dividing lines, 2=full */ unsigned short int border; /* Print a border around the table.
* 0=none, 1=dividing lines, 2=full */
char *fieldSep; /* field separator for unaligned text mode */ char *fieldSep; /* field separator for unaligned text mode */
char *tableAttr; /* attributes for HTML <table ...> */ char *tableAttr; /* attributes for HTML <table ...> */
} printTableOpt; } printTableOpt;
...@@ -39,19 +44,20 @@ typedef struct _printTableOpt { ...@@ -39,19 +44,20 @@ typedef struct _printTableOpt {
* - align is an 'l' or an 'r' for every column, if the output format needs it. * - align is an 'l' or an 'r' for every column, if the output format needs it.
* (You must specify this long enough. Otherwise anything could happen.) * (You must specify this long enough. Otherwise anything could happen.)
*/ */
void void printTable(const char *title, char **headers, char **cells, char **footers,
printTable(const char * title, char ** headers, char ** cells, char ** footers, const char *align,
const char * align, const printTableOpt * opt, FILE *fout);
const printTableOpt * opt, FILE * fout);
typedef struct _printQueryOpt { typedef struct _printQueryOpt
{
printTableOpt topt; /* the options above */ printTableOpt topt; /* the options above */
char * nullPrint; /* how to print null entities */ char *nullPrint; /* how to print null entities */
bool quote; /* quote all values as much as possible */ bool quote; /* quote all values as much as possible */
char * title; /* override title */ char *title; /* override title */
char ** footers; /* override footer (default is "(xx rows)") */ char **footers; /* override footer (default is "(xx
* rows)") */
} printQueryOpt; } printQueryOpt;
/* /*
...@@ -60,7 +66,7 @@ typedef struct _printQueryOpt { ...@@ -60,7 +66,7 @@ typedef struct _printQueryOpt {
* It calls the printTable above with all the things set straight. * It calls the printTable above with all the things set straight.
*/ */
void void
printQuery(PGresult * result, const printQueryOpt * opt, FILE * fout); printQuery(PGresult *result, const printQueryOpt * opt, FILE *fout);
#endif /* PRINT_H */ #endif /* PRINT_H */
...@@ -60,11 +60,11 @@ const char * ...@@ -60,11 +60,11 @@ const char *
get_prompt(PsqlSettings *pset, promptStatus_t status) get_prompt(PsqlSettings *pset, 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];
char buf[MAX_PROMPT_SIZE+1]; char buf[MAX_PROMPT_SIZE + 1];
bool esc = false; bool esc = false;
const char *p; const char *p;
const char * prompt_string; const char *prompt_string;
if (GetVariable(pset->vars, "quiet")) if (GetVariable(pset->vars, "quiet"))
return ""; return "";
...@@ -82,10 +82,10 @@ get_prompt(PsqlSettings *pset, promptStatus_t status) ...@@ -82,10 +82,10 @@ get_prompt(PsqlSettings *pset, promptStatus_t status)
destination[0] = '\0'; destination[0] = '\0';
for (p = prompt_string; for (p = prompt_string;
p && *p && strlen(destination)<MAX_PROMPT_SIZE; p && *p && strlen(destination) < MAX_PROMPT_SIZE;
p++) p++)
{ {
MemSet(buf, 0, MAX_PROMPT_SIZE+1); MemSet(buf, 0, MAX_PROMPT_SIZE + 1);
if (esc) if (esc)
{ {
switch (*p) switch (*p)
...@@ -99,11 +99,14 @@ get_prompt(PsqlSettings *pset, promptStatus_t status) ...@@ -99,11 +99,14 @@ get_prompt(PsqlSettings *pset, promptStatus_t status)
if (pset->db) if (pset->db)
strncpy(buf, PQdb(pset->db), MAX_PROMPT_SIZE); strncpy(buf, PQdb(pset->db), MAX_PROMPT_SIZE);
break; break;
case '~': { case '~':
const char * var; {
if (pset->db) { const char *var;
if ( strcmp(PQdb(pset->db), PQuser(pset->db))==0 ||
( (var = getenv("PGDATABASE")) && strcmp(var, PQdb(pset->db))==0) ) if (pset->db)
{
if (strcmp(PQdb(pset->db), PQuser(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);
...@@ -113,11 +116,13 @@ get_prompt(PsqlSettings *pset, promptStatus_t status) ...@@ -113,11 +116,13 @@ get_prompt(PsqlSettings *pset, promptStatus_t status)
/* 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';
} }
else else
buf[0] = '.'; buf[0] = '.';
...@@ -125,7 +130,8 @@ get_prompt(PsqlSettings *pset, promptStatus_t status) ...@@ -125,7 +130,8 @@ get_prompt(PsqlSettings *pset, promptStatus_t status)
break; break;
/* DB server port number */ /* DB server port number */
case '>': case '>':
if (pset->db) { if (pset->db)
{
if (PQhost(pset->db)) if (PQhost(pset->db))
strncpy(buf, PQport(pset->db), MAX_PROMPT_SIZE); strncpy(buf, PQport(pset->db), MAX_PROMPT_SIZE);
else else
...@@ -138,19 +144,29 @@ get_prompt(PsqlSettings *pset, promptStatus_t status) ...@@ -138,19 +144,29 @@ get_prompt(PsqlSettings *pset, promptStatus_t status)
strncpy(buf, PQuser(pset->db), MAX_PROMPT_SIZE); strncpy(buf, PQuser(pset->db), MAX_PROMPT_SIZE);
break; break;
case '0': case '1': case '2': case '3': case '4': case '0':
case '5': case '6': case '7': case '8': case '9': case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
{ {
long int l; long int l;
char * end; char *end;
l = strtol(p, &end, 0); l = strtol(p, &end, 0);
sprintf(buf, "%c", (unsigned char)l); sprintf(buf, "%c", (unsigned char) l);
p = end-1; p = end - 1;
break; break;
} }
case 'R': case 'R':
switch(status) { switch (status)
{
case PROMPT_READY: case PROMPT_READY:
if (!pset->db) if (!pset->db)
buf[0] = '!'; buf[0] = '!';
...@@ -182,7 +198,7 @@ get_prompt(PsqlSettings *pset, promptStatus_t status) ...@@ -182,7 +198,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] = '>';
...@@ -193,21 +209,23 @@ get_prompt(PsqlSettings *pset, promptStatus_t status) ...@@ -193,21 +209,23 @@ get_prompt(PsqlSettings *pset, promptStatus_t status)
/* execute command */ /* execute command */
case '`': case '`':
{ {
FILE * fd = NULL; FILE *fd = NULL;
char * file = strdup(p+1); char *file = strdup(p + 1);
int cmdend; int cmdend;
cmdend = strcspn(file, "`"); cmdend = strcspn(file, "`");
file[cmdend] = '\0'; file[cmdend] = '\0';
if (file) if (file)
fd = popen(file, "r"); fd = popen(file, "r");
if (fd) { if (fd)
fgets(buf, MAX_PROMPT_SIZE-1, fd); {
fgets(buf, MAX_PROMPT_SIZE - 1, fd);
pclose(fd); pclose(fd);
} }
if (buf[strlen(buf)-1] == '\n') if (buf[strlen(buf) - 1] == '\n')
buf[strlen(buf)-1] = '\0'; buf[strlen(buf) - 1] = '\0';
free(file); free(file);
p += cmdend+1; p += cmdend + 1;
break; break;
} }
...@@ -217,14 +235,15 @@ get_prompt(PsqlSettings *pset, promptStatus_t status) ...@@ -217,14 +235,15 @@ get_prompt(PsqlSettings *pset, promptStatus_t status)
char *name; char *name;
const char *val; const char *val;
int nameend; int nameend;
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 = interpolate_var(name, pset);
if (val) if (val)
strncpy(buf, val, MAX_PROMPT_SIZE); strncpy(buf, val, MAX_PROMPT_SIZE);
free(name); free(name);
p += nameend+1; p += nameend + 1;
break; break;
} }
...@@ -245,12 +264,10 @@ get_prompt(PsqlSettings *pset, promptStatus_t status) ...@@ -245,12 +264,10 @@ get_prompt(PsqlSettings *pset, promptStatus_t status)
esc = false; esc = false;
} }
if (!esc) { if (!esc)
strncat(destination, buf, MAX_PROMPT_SIZE-strlen(destination)); strncat(destination, buf, MAX_PROMPT_SIZE - strlen(destination));
}
} }
destination[MAX_PROMPT_SIZE] = '\0'; destination[MAX_PROMPT_SIZE] = '\0';
return destination; return destination;
} }
...@@ -3,7 +3,8 @@ ...@@ -3,7 +3,8 @@
#include "settings.h" #include "settings.h"
typedef enum _promptStatus { typedef enum _promptStatus
{
PROMPT_READY, PROMPT_READY,
PROMPT_CONTINUE, PROMPT_CONTINUE,
PROMPT_COMMENT, PROMPT_COMMENT,
...@@ -13,7 +14,7 @@ typedef enum _promptStatus { ...@@ -13,7 +14,7 @@ typedef enum _promptStatus {
} promptStatus_t; } promptStatus_t;
const char * const char *
get_prompt(PsqlSettings *pset, promptStatus_t status); get_prompt(PsqlSettings *pset, promptStatus_t status);
#endif /* PROMPT_H */ #endif /* PROMPT_H */
This diff is collapsed.
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* *
* Copyright (c) 1994, Regents of the University of California * Copyright (c) 1994, Regents of the University of California
* *
* $Id: psqlHelp.h,v 1.80 1999/10/29 23:52:22 momjian Exp $ * $Id: psqlHelp.h,v 1.81 1999/11/04 23:14:29 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -384,5 +384,6 @@ TIMEZONE|XACTISOLEVEL|CLIENT_ENCODING|SERVER_ENCODING"}, ...@@ -384,5 +384,6 @@ TIMEZONE|XACTISOLEVEL|CLIENT_ENCODING|SERVER_ENCODING"},
\tVACUUM [VERBOSE] [ANALYZE] [table]\n\ \tVACUUM [VERBOSE] [ANALYZE] [table]\n\
\tor\n\ \tor\n\
\tVACUUM [VERBOSE] ANALYZE [table [(column_name1, ...column_nameN)]];"}, \tVACUUM [VERBOSE] ANALYZE [table [(column_name1, ...column_nameN)]];"},
{NULL, NULL, NULL} /* important to keep a NULL terminator here!*/ {NULL, NULL, NULL} /* important to keep a NULL terminator
* here! */
}; };
...@@ -29,15 +29,18 @@ typedef struct _psqlSettings ...@@ -29,15 +29,18 @@ typedef struct _psqlSettings
char *gfname; /* one-shot file output argument for \g */ char *gfname; /* one-shot file output argument for \g */
bool notty; /* stdin or stdout is not a tty (as determined on startup) */ bool notty; /* stdin or stdout is not a tty (as
* determined on startup) */
bool useReadline; /* use libreadline routines */ bool useReadline; /* use libreadline routines */
bool useHistory; bool useHistory;
bool getPassword; /* prompt the user for a username and bool getPassword; /* prompt the user for a username and
password */ * password */
FILE * cur_cmd_source; /* describe the status of the current main loop */ FILE *cur_cmd_source; /* describe the status of the current main
* loop */
bool cur_cmd_interactive; bool cur_cmd_interactive;
bool has_client_encoding; /* was PGCLIENTENCODING set on startup? */ bool has_client_encoding; /* was PGCLIENTENCODING set on
* startup? */
} PsqlSettings; } PsqlSettings;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -3,12 +3,11 @@ ...@@ -3,12 +3,11 @@
/* The cooler version of strtok() which knows about quotes and doesn't /* The cooler version of strtok() which knows about quotes and doesn't
* overwrite your input */ * overwrite your input */
extern char * extern char *strtokx(const char *s,
strtokx(const char *s,
const char *delim, const char *delim,
const char *quote, const char *quote,
char escape, char escape,
char * was_quoted, char *was_quoted,
unsigned int * token_pos); unsigned int *token_pos);
#endif /* STRINGUTILS_H */ #endif /* STRINGUTILS_H */
This diff is collapsed.
...@@ -13,20 +13,21 @@ ...@@ -13,20 +13,21 @@
#define VALID_VARIABLE_CHARS "abcdefghijklmnopqrstuvwxyz0123456789_" #define VALID_VARIABLE_CHARS "abcdefghijklmnopqrstuvwxyz0123456789_"
struct _variable { struct _variable
char * name; {
char * value; char *name;
struct _variable * next; char *value;
struct _variable *next;
}; };
typedef struct _variable * VariableSpace; typedef struct _variable *VariableSpace;
VariableSpace CreateVariableSpace(void); VariableSpace CreateVariableSpace(void);
const char * GetVariable(VariableSpace space, const char * name); const char *GetVariable(VariableSpace space, const char *name);
bool GetVariableBool(VariableSpace space, const char * name); bool GetVariableBool(VariableSpace space, const char *name);
bool SetVariable(VariableSpace space, const char * name, const char * value); bool SetVariable(VariableSpace space, const char *name, const char *value);
bool DeleteVariable(VariableSpace space, const char * name); bool DeleteVariable(VariableSpace space, const char *name);
void DestroyVariableSpace(VariableSpace space); void DestroyVariableSpace(VariableSpace space);
......
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