Skip to content

Instantly share code, notes, and snippets.

@tmc
Created December 6, 2010 05:26
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tmc/81b917d39b4b752029fd to your computer and use it in GitHub Desktop.
Save tmc/81b917d39b4b752029fd to your computer and use it in GitHub Desktop.
commit 99dc4e3b4335a1b927fc87878089cde4e07a808c
Author: Julian Assange <proff@suburbia.net>
Date: Wed Aug 21 00:22:41 1996 +0000
command line flag for expanded display '-x' had logic reversed
src/bin/psql/psql.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
commit dfca092633dae8a6f2e5a3db859fe3faec6f2de6
Author: Julian Assange <proff@suburbia.net>
Date: Tue Aug 6 20:23:14 1996 +0000
applied kurt's patch to fix unlikely, but potential, string underflow
problem in psql
src/bin/psql/stringutils.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
commit 7ef04b25cc59f87abf80ec25c3c1b229bf77a37e
Author: Julian Assange <proff@suburbia.net>
Date: Tue Aug 6 00:40:12 1996 +0000
added patch from kurt that fixes memory leak (didn't free line buffer
for slash commands)
src/bin/psql/psql.c | 10 +++++++---
1 files changed, 7 insertions(+), 3 deletions(-)
commit ed3240d093e0fda4a8caa33b85a2636b6400c80a
Author: Julian Assange <proff@suburbia.net>
Date: Sun Jul 28 06:48:42 1996 +0000
bugfix: if NOREADLINE was not defined and input was not from a tty, then
the getopt() was not executed.
src/bin/psql/psql.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
commit 76bc8cb97fc35673c42fe84fe6a9d6887260419a
Author: Julian Assange <proff@suburbia.net>
Date: Thu Jul 25 06:46:35 1996 +0000
Large re-write/enhancement. In pg-101 Jolly only included a smaller part
of my (proff) patch. This is the rest of it, with a few, mainly aesthetic
changes. I've removed a lot of redundency from the original code,
added support for the new PQprint() routines in libpq, expanded tables,
and a few generally nifty ways of massaging data in and out of the
backend. Still needs some good stress testing.
src/bin/psql/psql.c | 843 ++++++++++++++++++++++++++++++---------------------
1 files changed, 501 insertions(+), 342 deletions(-)
commit 23c7ff0b3c38657081590430d08ef48bb5bde759
Author: Julian Assange <proff@suburbia.net>
Date: Thu Jul 25 06:21:11 1996 +0000
PQprint() routines. The older code is still there for historical
compatibility. There isn't much difference here against my previous
PQprint() code, except that you can add optional arguments to the
<table args> in html.
src/interfaces/libpq/fe-exec.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
commit 99dc4e3b4335a1b927fc87878089cde4e07a808c
Author: Julian Assange <proff@suburbia.net>
Date: Wed Aug 21 00:22:41 1996 +0000
command line flag for expanded display '-x' had logic reversed
diff --git a/src/bin/psql/psql.c b/src/bin/psql/psql.c
index 5ac2079..8ad2dd4 100644
--- a/src/bin/psql/psql.c
+++ b/src/bin/psql/psql.c
@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/bin/psql/Attic/psql.c,v 1.19 1996/08/14 05:44:25 scrappy Exp $
+ * $Header: /cvsroot/pgsql/src/bin/psql/Attic/psql.c,v 1.20 1996/08/21 00:22:41 julian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1213,7 +1213,7 @@ main(int argc, char **argv)
settings.opt.tableOpt = optarg;
break;
case 'x':
- settings.opt.expanded = 0;
+ settings.opt.expanded = 1;
break;
default:
usage(argv[0]);
commit dfca092633dae8a6f2e5a3db859fe3faec6f2de6
Author: Julian Assange <proff@suburbia.net>
Date: Tue Aug 6 20:23:14 1996 +0000
applied kurt's patch to fix unlikely, but potential, string underflow
problem in psql
diff --git a/src/bin/psql/stringutils.c b/src/bin/psql/stringutils.c
index 294ce40..daeb120 100644
--- a/src/bin/psql/stringutils.c
+++ b/src/bin/psql/stringutils.c
@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/bin/psql/stringutils.c,v 1.2 1996/07/28 07:08:15 scrappy Exp $
+ * $Header: /cvsroot/pgsql/src/bin/psql/stringutils.c,v 1.3 1996/08/06 20:23:14 julian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -42,7 +42,7 @@ char *rightTrim(char *s)
{
char *sEnd;
sEnd = s+strlen(s)-1;
- while (isspace(*sEnd))
+ while (sEnd >= s && isspace(*sEnd))
sEnd--;
if (sEnd < s)
s[0]='\0';
commit 7ef04b25cc59f87abf80ec25c3c1b229bf77a37e
Author: Julian Assange <proff@suburbia.net>
Date: Tue Aug 6 00:40:12 1996 +0000
added patch from kurt that fixes memory leak (didn't free line buffer
for slash commands)
diff --git a/src/bin/psql/psql.c b/src/bin/psql/psql.c
index c65d83c..6ab76ec 100644
--- a/src/bin/psql/psql.c
+++ b/src/bin/psql/psql.c
@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/bin/psql/Attic/psql.c,v 1.15 1996/07/31 02:11:23 scrappy Exp $
+ * $Header: /cvsroot/pgsql/src/bin/psql/Attic/psql.c,v 1.16 1996/08/06 00:40:12 julian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1064,10 +1064,14 @@ MainLoop(PsqlSettings *settings, FILE *source)
slashCmdStatus = HandleSlashCmds(settings,
line,
query);
- if (slashCmdStatus == 1)
+ if (slashCmdStatus == 1) {
+ free(line);
continue;
- if (slashCmdStatus == 2)
+ }
+ if (slashCmdStatus == 2) {
+ free(line);
break;
+ }
if (slashCmdStatus == 0)
sendQuery = 1;
}
commit ed3240d093e0fda4a8caa33b85a2636b6400c80a
Author: Julian Assange <proff@suburbia.net>
Date: Sun Jul 28 06:48:42 1996 +0000
bugfix: if NOREADLINE was not defined and input was not from a tty, then
the getopt() was not executed.
diff --git a/src/bin/psql/psql.c b/src/bin/psql/psql.c
index 40c3603..8180a3e 100644
--- a/src/bin/psql/psql.c
+++ b/src/bin/psql/psql.c
@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/bin/psql/Attic/psql.c,v 1.10 1996/07/27 04:38:22 scrappy Exp $
+ * $Header: /cvsroot/pgsql/src/bin/psql/Attic/psql.c,v 1.11 1996/07/28 06:48:42 julian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1134,8 +1134,8 @@ main(int argc, char** argv)
settings.opt.pager = 1;
if (!isatty(0) || !isatty(1))
settings.quiet = settings.notty = 1;
- else
#ifndef NOREADLINE
+ else
settings.useReadline = 1;
#endif
commit 76bc8cb97fc35673c42fe84fe6a9d6887260419a
Author: Julian Assange <proff@suburbia.net>
Date: Thu Jul 25 06:46:35 1996 +0000
Large re-write/enhancement. In pg-101 Jolly only included a smaller part
of my (proff) patch. This is the rest of it, with a few, mainly aesthetic
changes. I've removed a lot of redundency from the original code,
added support for the new PQprint() routines in libpq, expanded tables,
and a few generally nifty ways of massaging data in and out of the
backend. Still needs some good stress testing.
diff --git a/src/bin/psql/psql.c b/src/bin/psql/psql.c
index 2201c06..4bb783f 100644
--- a/src/bin/psql/psql.c
+++ b/src/bin/psql/psql.c
@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/bin/psql/Attic/psql.c,v 1.6 1996/07/23 03:03:43 scrappy Exp $
+ * $Header: /cvsroot/pgsql/src/bin/psql/Attic/psql.c,v 1.7 1996/07/25 06:46:35 julian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -16,8 +16,8 @@
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <unistd.h>
#include <fcntl.h>
-
#include "libpq-fe.h"
#include "stringutils.h"
@@ -32,52 +32,57 @@ extern char *readline(char *); /* in rlstubs.c */
#include "history.h"
#else
#include <readline/readline.h>
-#include <history.h>
+#include <readline/history.h>
#endif
#endif
#define MAX_QUERY_BUFFER 20000
-#define MAX_FIELD_SEP_LENGTH 40
#define COPYBUFSIZ 8192
-#define DEFAULT_FIELD_SEP " "
+#define DEFAULT_FIELD_SEP "|"
#define DEFAULT_EDITOR "vi"
#define DEFAULT_SHELL "/bin/sh"
typedef struct _psqlSettings {
- int echoQuery; /* if 1, echo the query before sending it */
- int quiet; /* run quietly, no messages, no promt */
- int singleStep; /* if 1, prompt for each query */
- int singleLineMode; /* if 1, query terminated by newline */
- int useReadline; /* use the readline routines or not */
- int printHeader; /* print output field headers or not */
- int fillAlign; /* fill align the fields */
- FILE *queryFout; /* where to send the query results */
- char fieldSep[MAX_FIELD_SEP_LENGTH]; /* field separator */
+ PGconn *db; /* connection to backend */
+ FILE *queryFout; /* where to send the query results */
+ PQprintOpt opt; /* options to be passed to PQprint */
+ char *prompt; /* prompt to display */
+ char *gfname; /* one-shot file output argument for \g */
+ bool notty; /* input or output is not a tty */
+ bool pipe; /* queryFout is from a popen() */
+ bool echoQuery; /* echo the query before sending it */
+ bool quiet; /* run quietly, no messages, no promt */
+ bool singleStep; /* prompt before for each query */
+ bool singleLineMode; /* query terminated by newline */
+ bool useReadline; /* use libreadline routines */
} PsqlSettings;
/* declarations for functions in this file */
static void usage(char* progname);
static void slashUsage();
-static void handleCopyOut(PGresult *res, int quiet);
-static void handleCopyIn(PGresult *res, int quiet);
-static int tableList(PGconn* conn, int deep_tablelist);
-static int tableDesc(PGconn* conn, char* table);
+static void handleCopyOut(PGresult *res, bool quiet);
+static void handleCopyIn(PGresult *res, bool quiet);
+static int tableList(PsqlSettings *ps, bool deep_tablelist);
+static int tableDesc(PsqlSettings *ps, char *table);
char* gets_noreadline(char* prompt, FILE* source);
char* gets_readline(char* prompt, FILE* source);
char* gets_fromFile(char* prompt, FILE* source);
-int listAllDbs(PGconn *db, PsqlSettings *settings);
-int SendQuery(PGconn* db, char* query, PsqlSettings *settings);
-int HandleSlashCmds(PGconn** db_ptr,
+int listAllDbs(PsqlSettings *settings);
+int SendQuery(PsqlSettings *settings, char* query);
+int HandleSlashCmds(PsqlSettings *settings,
char *line,
- char** prompt_ptr,
- char *query,
- PsqlSettings *settings);
-int MainLoop(PGconn** db_ptr, FILE *source, PsqlSettings *settings);
-FILE* setFout(char *fname);
+ char *query);
+int MainLoop(PsqlSettings *settings, FILE *source);
+/* probably should move this into libpq */
+void PQprint(FILE *fp,
+ PGresult *res,
+ PQprintOpt *po
+ );
+FILE* setFout(PsqlSettings *ps, char *fname);
/*
* usage
@@ -89,22 +94,24 @@ usage(char* progname)
{
fprintf(stderr,"Usage: %s [options] [dbname]\n",progname);
fprintf(stderr,"\t -a authsvc set authentication service\n");
- fprintf(stderr,"\t -A turn off fill-justification when printing out attributes\n");
+ fprintf(stderr,"\t -A turn off alignment when printing out attributes\n");
fprintf(stderr,"\t -c query run single query (slash commands too)\n");
fprintf(stderr,"\t -d dbName specify database name\n");
fprintf(stderr,"\t -e echo the query sent to the backend\n");
fprintf(stderr,"\t -f filename use file as a source of queries\n");
fprintf(stderr,"\t -F sep set the field separator (default is " ")\n");
- fprintf(stderr,"\t -h help information\n");
- fprintf(stderr,"\t -H host set database server host\n");
+ fprintf(stderr,"\t -h host set database server host\n");
+ fprintf(stderr,"\t -H turn on html3.0 table output\n");
fprintf(stderr,"\t -l list available databases\n");
fprintf(stderr,"\t -n don't use readline library\n");
- fprintf(stderr,"\t -o filename send output to filename\n");
+ fprintf(stderr,"\t -o filename send output to filename or (|pipe)\n");
fprintf(stderr,"\t -p port set port number\n");
fprintf(stderr,"\t -q run quietly (no messages, no prompts)\n");
fprintf(stderr,"\t -s single step mode (prompts for each query)\n");
fprintf(stderr,"\t -S single line mode (i.e. query terminated by newline)\n");
- fprintf(stderr,"\t -T turn off printing of attribute names\n");
+ fprintf(stderr,"\t -t turn off printing of attribute headers\n");
+ fprintf(stderr,"\t -T html set html3.0 table command options (cf. -H)\n");
+ fprintf(stderr,"\t -x turn on expanded output (field names on left)");
exit(1);
}
@@ -113,29 +120,60 @@ usage(char* progname)
* print out usage for the backslash commands
*/
+char *on(bool f)
+{
+ return f? "on": "off";
+}
+
static void
-slashUsage()
+slashUsage(PsqlSettings *ps)
{
- fprintf(stderr,"\t \\a -- toggle fill-justification of display of attributes\n");
+ fprintf(stderr,"\t \\a -- toggle field-alignment (currenty %s)\n", on(ps->opt.align));
+ fprintf(stderr,"\t \\C [<captn>] -- set html3 caption (currently '%s')\n", ps->opt.caption? ps->opt.caption: "");
+ fprintf(stderr,"\t \\c <dbname> -- connect to new database (currently '%s')\n", PQdb(ps->db));
fprintf(stderr,"\t \\d [<table>] -- list tables in database or columns in <table>\n");
fprintf(stderr,"\t \\d * -- list tables in database and columns in all tables\n");
fprintf(stderr,"\t \\e [<fname>] -- edit the current query buffer or <fname>\n");
- fprintf(stderr,"\t \\f <sep> -- change field separator\n");
- fprintf(stderr,"\t \\g -- query to backend\n");
- fprintf(stderr,"\t \\h <command> -- help on syntax of sql commands\n");
+ fprintf(stderr,"\t \\f [<sep>] -- change field separater (currently '%s')\n", ps->opt.fieldSep);
+ fprintf(stderr,"\t \\g [<fname>] -- send query to backend [and place results in <fname>]\n");
+ fprintf(stderr,"\t \\g |<cmd> -- send query to backend and pipe results into <cmd>\n");
+ fprintf(stderr,"\t \\h [<cmd>] -- help on syntax of sql commands\n");
fprintf(stderr,"\t \\h * -- complete description of all sql commands\n");
- fprintf(stderr,"\t \\g -- send query to backend\n");
- fprintf(stderr,"\t \\i <fname> -- read queries from filename\n");
+ fprintf(stderr,"\t \\H -- toggle html3 output (currently %s)\n", on(ps->opt.html3));
+ fprintf(stderr,"\t \\i <fname> -- read and execute queries from filename\n");
fprintf(stderr,"\t \\l -- list all databases\n");
- fprintf(stderr,"\t \\o [<fname>] -- send query results file named <fname> or stdout\n");
+ fprintf(stderr,"\t \\m -- toggle monitor-like type-setting (currently %s)\n", on(ps->opt.standard));
+ fprintf(stderr,"\t \\o [<fname>] -- send all query results to <fname> or stdout\n");
+ fprintf(stderr,"\t \\o |<cmd> -- pipe all query results through <cmd>\n");
fprintf(stderr,"\t \\p -- print the current query buffer\n");
fprintf(stderr,"\t \\q -- quit\n");
- fprintf(stderr,"\t \\s [<fname>] -- save or print history\n");
- fprintf(stderr,"\t \\t -- toggle output field headers (defaults to on)\n");
- fprintf(stderr,"\t \\! [<cmd>] -- shell escape\n");
+ fprintf(stderr,"\t \\r [<fname>] -- edit <fname> then execute on save\n");
+ fprintf(stderr,"\t \\s [<fname>] -- print history or save it in <fname>\n");
+ fprintf(stderr,"\t \\t -- toggle table output header (currently %s)\n", on(ps->opt.header));
+ fprintf(stderr,"\t \\T [<html>] -- set html3.0 <table ...> options (currently '%s')\n", ps->opt.tableOpt? ps->opt.tableOpt: "");
+ fprintf(stderr,"\t \\x -- toggle expanded output (currently %s)\n", on(ps->opt.expanded));
+ fprintf(stderr,"\t \\z -- zorch current query buffer (i.e clear it)\n");
+ fprintf(stderr,"\t \\! [<cmd>] -- shell escape or command\n");
fprintf(stderr,"\t \\? -- help\n");
}
+PGresult *
+PSQLexec(PsqlSettings *ps, char *query)
+{
+ PGresult *res = PQexec(ps->db, query);
+ if (!res)
+ fputs(PQerrorMessage(ps->db), stderr);
+ else
+ {
+ if (PQresultStatus(res)==PGRES_COMMAND_OK ||
+ PQresultStatus(res)==PGRES_TUPLES_OK)
+ return res;
+ if (!ps->quiet)
+ fputs(PQerrorMessage(ps->db), stderr);
+ PQclear(res);
+ }
+ return NULL;
+}
/*
* listAllDbs
*
@@ -144,50 +182,37 @@ slashUsage()
*
*
*/
-int
-listAllDbs(PGconn *db, PsqlSettings *settings)
+
+int
+listAllDbs(PsqlSettings *ps)
{
PGresult *results;
char* query = "select * from pg_database;";
- results = PQexec(db, query);
- if (results == NULL) {
- fprintf(stderr,"%s", PQerrorMessage(db));
+ if (!(results=PSQLexec(ps, query)))
return 1;
- }
-
- if (PQresultStatus(results) != PGRES_TUPLES_OK)
- {
- fprintf(stderr,"Unexpected error from executing: %s\n", query);
- return 2;
- }
else
{
- PQdisplayTuples(results,
- settings->queryFout,
- settings->fillAlign,
- settings->fieldSep,
- settings->printHeader,
- settings->quiet);
+ PQprint(ps->queryFout,
+ results,
+ &ps->opt);
PQclear(results);
return 0;
}
}
/*
- * tableList (PGconn* conn)
*
* List The Database Tables
* returns 0 if all went well
*
*/
int
-tableList (PGconn* conn, int deep_tablelist)
+tableList (PsqlSettings *ps, bool deep_tablelist)
{
char listbuf[256];
int nColumns;
int i;
- char* ru;
char* rk;
char* rr;
@@ -203,17 +228,8 @@ tableList (PGconn* conn, int deep_tablelist)
add in the int4oideq function */
strcat(listbuf," and usesysid = relowner");
strcat(listbuf," ORDER BY relname ");
- res = PQexec(conn,listbuf);
- if (res == NULL) {
- fprintf(stderr,"%s", PQerrorMessage(conn));
- return (-1);
- }
-
- if ((PQresultStatus(res) != PGRES_TUPLES_OK) || (PQntuples(res) <= 0)) {
- fprintf(stderr,"No tables found in database %s.\n", PQdb(conn));
- PQclear(res);
- return (-1);
- }
+ if (!(res=PSQLexec(ps, listbuf)))
+ return -1;
/* first, print out the attribute names */
nColumns = PQntuples(res);
@@ -236,14 +252,14 @@ tableList (PGconn* conn, int deep_tablelist)
PQclear(res);
for (i=0; i < nColumns; i++) {
- tableDesc(conn,table[i]);
+ tableDesc(ps, table[i]);
}
free(table);
}
else {
/* Display the information */
- printf ("\nDatabase = %s\n", PQdb(conn));
+ printf ("\nDatabase = %s\n", PQdb(ps->db));
printf (" +------------------+----------------------------------+----------+\n");
printf (" | Owner | Relation | Type |\n");
printf (" +------------------+----------------------------------+----------+\n");
@@ -272,7 +288,7 @@ tableList (PGconn* conn, int deep_tablelist)
}
/*
- * Describe a table (PGconn* conn, char* table)
+ * Describe a table
*
* Describe the columns in a database table.
* returns 0 if all went well
@@ -280,7 +296,7 @@ tableList (PGconn* conn, int deep_tablelist)
*
*/
int
-tableDesc (PGconn* conn, char* table)
+tableDesc (PsqlSettings *ps, char *table)
{
char descbuf[256];
int nColumns;
@@ -302,16 +318,8 @@ tableDesc (PGconn* conn, char* table)
strcat(descbuf," and a.attrelid = c.oid ");
strcat(descbuf," and a.atttypid = t.oid ");
strcat(descbuf," ORDER BY attnum ");
- res = PQexec(conn,descbuf);
- if (res == NULL) {
- fprintf(stderr,"%s", PQerrorMessage(conn));
- return (-1);
- }
- if ((PQresultStatus(res) != PGRES_TUPLES_OK) || (PQntuples(res) <= 0)) {
- fprintf(stderr,"Couldn't find table %s!\n", table);
- PQclear(res);
- return (-1);
- }
+ if (!(res = PSQLexec(ps, descbuf)))
+ return -1;
/* first, print out the attribute names */
nColumns = PQntuples(res);
if (nColumns > 0)
@@ -332,15 +340,15 @@ tableDesc (PGconn* conn, char* table)
rsize = atoi(PQgetvalue(res,i,3));
if (strcmp(rtype, "text") == 0) {
printf ("%-32.32s |", rtype);
- printf ("%-6s |", "var" );
+ printf ("%6s |", "var" );
}
else if (strcmp(rtype, "bpchar") == 0) {
printf ("%-32.32s |", "char");
- printf ("%-6i |", rsize > 0 ? rsize - 4 : 0 );
+ printf ("%6i |", rsize > 0 ? rsize - 4 : 0 );
}
else if (strcmp(rtype, "varchar") == 0) {
printf ("%-32.32s |", rtype);
- printf ("%-6i |", rsize > 0 ? rsize - 4 : 0 );
+ printf ("%6i |", rsize > 0 ? rsize - 4 : 0 );
}
else {
/* array types start with an underscore */
@@ -355,9 +363,9 @@ tableDesc (PGconn* conn, char* table)
free(newname);
}
if (rsize > 0)
- printf ("%-6i |", rsize);
+ printf ("%6i |", rsize);
else
- printf ("%-6s |", "var");
+ printf ("%6s |", "var");
}
printf("\n");
}
@@ -396,7 +404,6 @@ gets_readline(char* prompt, FILE* source)
return (readline(prompt));
}
-
/*
* gets_fromFile prompt source
*
@@ -426,14 +433,12 @@ gets_fromFile(char* prompt, FILE* source)
}
/*
- * SendQuery:
- SendQuery: send the query string to the backend
- *
+ * SendQuery: send the query string to the backend
* return 0 if the query executed successfully
* returns 1 otherwise
*/
int
-SendQuery(PGconn* db, char* query, PsqlSettings *settings)
+SendQuery(PsqlSettings *settings, char *query)
{
PGresult* results;
PGnotify* notify;
@@ -454,20 +459,41 @@ SendQuery(PGconn* db, char* query, PsqlSettings *settings)
gets_fromFile("",stdin);
}
- results = PQexec(db, query);
+ results = PQexec(settings->db, query);
if (results == NULL) {
- fprintf(stderr,"%s",PQerrorMessage(db));
+ fprintf(stderr,"%s",PQerrorMessage(settings->db));
return 1;
}
switch (PQresultStatus(results)) {
case PGRES_TUPLES_OK:
- PQdisplayTuples(results,
- settings->queryFout,
- settings->fillAlign,
- settings->fieldSep,
- settings->printHeader,
- settings->quiet);
+ if (settings->gfname)
+ {
+ PsqlSettings ps=*settings;
+ FILE *fp;
+ ps.queryFout=stdout;
+ fp=setFout(&ps, settings->gfname);
+ if (!fp || fp==stdout)
+ {
+ status = 1;
+ break;
+ }
+ PQprint(fp,
+ results,
+ &(settings->opt));
+ if (ps.pipe)
+ pclose(fp);
+ else
+ fclose(fp);
+ settings->gfname=NULL;
+ break;
+ } else
+ {
+ PQprint(settings->queryFout,
+ results,
+ &(settings->opt));
+ fflush(settings->queryFout);
+ }
PQclear(results);
break;
case PGRES_EMPTY_QUERY:
@@ -475,7 +501,7 @@ SendQuery(PGconn* db, char* query, PsqlSettings *settings)
break;
case PGRES_COMMAND_OK:
if (!settings->quiet)
- fprintf(stdout,"%s\n",PQcmdStatus(results));
+ fprintf(stdout,"%s\n", PQcmdStatus(results));
break;
case PGRES_COPY_OUT:
handleCopyOut(results, settings->quiet);
@@ -487,13 +513,12 @@ SendQuery(PGconn* db, char* query, PsqlSettings *settings)
case PGRES_FATAL_ERROR:
case PGRES_BAD_RESPONSE:
status = 1;
- fprintf(stderr,"%s",PQerrorMessage(db));
+ fprintf(stderr,"%s",PQerrorMessage(settings->db));
break;
-
}
/* check for asynchronous returns */
- notify = PQnotifies(db);
+ notify = PQnotifies(settings->db);
if (notify) {
fprintf(stderr,"ASYNC NOTIFY of '%s' from backend pid '%d' received\n",
notify->relname, notify->be_pid);
@@ -504,6 +529,71 @@ SendQuery(PGconn* db, char* query, PsqlSettings *settings)
}
+void
+editFile(char *fname)
+{
+ char *editorName;
+ char *sys;
+ editorName = getenv("EDITOR");
+ if (!editorName)
+ editorName = DEFAULT_EDITOR;
+ sys=malloc(strlen(editorName)+strlen(fname)+32+1);
+ if (!sys)
+ {
+ perror("malloc");
+ exit(1);
+ }
+ sprintf(sys, "exec '%s' '%s'", editorName, fname);
+ system(sys);
+ free(sys);
+}
+
+bool
+toggle(PsqlSettings *settings, bool *sw, char *msg)
+{
+ *sw= !*sw;
+ if (!settings->quiet)
+ fprintf(stderr, "turned %s %s\n", on(*sw), msg);
+ return *sw;
+}
+
+char *
+decode(char *s)
+{
+ char *p, *d;
+ bool esc=0;
+ for (d=p=s; *p; p++)
+ {
+ char c=*p;
+ if (esc)
+ {
+ switch(*p)
+ {
+ case 'n':
+ c='\n';
+ break;
+ case 'r':
+ c='\r';
+ break;
+ case 't':
+ c='\t';
+ break;
+ case 'f':
+ c='\f';
+ break;
+ }
+ esc=0;
+ } else
+ if (c=='\\')
+ {
+ esc=1;
+ continue;
+ }
+ *d++=c;
+ }
+ *d='\0';
+}
+
/*
HandleSlashCmds:
@@ -519,189 +609,161 @@ SendQuery(PGconn* db, char* query, PsqlSettings *settings)
2 - terminate processing of this query entirely
*/
int
-HandleSlashCmds(PGconn** db_ptr,
+HandleSlashCmds(PsqlSettings *settings,
char* line,
- char** prompt_ptr,
- char *query,
- PsqlSettings *settings)
+ char *query)
{
- int status = 0;
- PGconn* db = *db_ptr;
- char* dbname = PQdb(db);
+ int status = 1;
char *optarg = NULL;
int len;
len = strlen(line);
if (len > 2)
+ {
optarg = leftTrim(line+2);
+ decode(optarg);
+ }
switch (line[1])
{
- case 'a': /* toggles to fill fields on output */
- if (settings->fillAlign)
- settings->fillAlign = 0;
- else
- settings->fillAlign = 1;
- if (!settings->quiet)
- fprintf(stderr,"turning %s fill-justification\n",
- (settings->fillAlign) ? "on" : "off" );
+ case 'a': /* toggles to align fields on output */
+ toggle(settings, &settings->opt.align, "field alignment");
+ break;
+ case 'C': /* define new caption */
+ if (settings->opt.caption)
+ free(settings->opt.caption);
+ if (!optarg)
+ settings->opt.caption=NULL;
+ else
+ if (!(settings->opt.caption=dupstr(optarg)))
+ {
+ perror("malloc");
+ exit(1);
+ }
break;
case 'c': /* \c means connect to new database */
{
+ char *dbname=PQdb(settings->db);
if (!optarg) {
fprintf(stderr,"\\c must be followed by a database name\n");
- status = 1;
- break;
- }
- if (strcmp(optarg, dbname) == 0) {
- fprintf(stderr,"already connected to %s\n", dbname);
- status = 1;
break;
}
- else {
- PGconn *olddb;
+ {
+ PGconn *olddb=settings->db;
- printf("closing connection to database:%s\n", dbname);
- olddb = db;
- db = PQsetdb(PQhost(olddb), PQport(olddb), NULL, NULL, optarg);
- *db_ptr = db;
+ printf("closing connection to database: %s\n", dbname);
+ settings->db = PQsetdb(PQhost(olddb), PQport(olddb), NULL, NULL, optarg);
printf("connecting to new database: %s\n", optarg);
- if (PQstatus(db) == CONNECTION_BAD) {
- fprintf(stderr,"%s\n", PQerrorMessage(db));
+ if (PQstatus(settings->db) == CONNECTION_BAD) {
+ fprintf(stderr,"%s\n", PQerrorMessage(settings->db));
printf("reconnecting to %s\n", dbname);
- db = PQsetdb(PQhost(olddb), PQport(olddb),
+ settings->db = PQsetdb(PQhost(olddb), PQport(olddb),
NULL, NULL, dbname);
- *db_ptr = db;
- if (PQstatus(db) == CONNECTION_BAD) {
+ if (PQstatus(settings->db) == CONNECTION_BAD) {
fprintf(stderr,
- "could not reconnect to %s. exiting\n", dbname);
+ "could not reconnect to %s. exiting\n", dbname);
exit(2);
}
- status = 1;
break;
}
PQfinish(olddb);
- free(*prompt_ptr);
- *prompt_ptr = malloc(strlen(optarg) + 10);
- sprintf(*prompt_ptr,"%s=> ", optarg);
- status = 1;
+ free(settings->prompt);
+ settings->prompt = malloc(strlen(PQdb(settings->db)) + 10);
+ sprintf(settings->prompt,"%s=> ", PQdb(settings->db));
break;
}
}
break;
case 'd': /* \d describe tables or columns in a table */
- {
if (!optarg) {
- tableList(db,0);
- status = 1;
+ tableList(settings, 0);
break;
- }
- if ( strcmp(optarg,"*") == 0 ) {
- tableList(db, 0);
- tableList(db, 1);
+ }
+ if (strcmp(optarg, "*") == 0 ) {
+ tableList(settings, 0);
+ tableList(settings, 1);
}
else {
- tableDesc(db,optarg);
+ tableDesc(settings, optarg);
}
- status = 1;
break;
- }
case 'e':
{
- char s[256];
int fd;
- int ql = strlen(query);
- int f_arg = 0;
+ char tmp[64];
+ char *fname;
int cc;
+ int ql = strlen(query);
if (optarg)
- {
- f_arg = 1;
- strcpy(s, optarg);
- }
+ fname=optarg;
else
- {
- sprintf(s, "/tmp/psql.%d.%d", geteuid(), getpid());
- unlink(s);
+ {
+ sprintf(tmp, "/tmp/psql.%d.%d", geteuid(), getpid());
+ fname=tmp;
+ unlink(tmp);
if (ql)
{
- if ((fd=open(s, O_EXCL|O_CREAT|O_WRONLY, 0600))==-1)
+ if ((fd=open(tmp, O_EXCL|O_CREAT|O_WRONLY, 0600))==-1)
{
- perror(s);
+ perror(tmp);
break;
}
if (query[ql-1]!='\n')
strcat(query, "\n");
if (write(fd, query, ql)!=ql)
{
- perror(s);
+ perror(tmp);
close(fd);
- unlink(s);
+ unlink(tmp);
break;
}
close(fd);
}
}
+ editFile(fname);
+ if ((fd=open(fname, O_RDONLY))==-1)
{
- char sys[256];
- char *editorName;
- editorName = getenv("EDITOR");
- if (editorName == NULL)
- editorName = DEFAULT_EDITOR;
- sprintf(sys, "exec %s %s", editorName, s);
- system(sys);
- }
- if ((fd=open(s, O_RDONLY))==-1)
- {
- if (!f_arg)
- unlink(s);
+ perror(fname);
+ if (!optarg)
+ unlink(fname);
break;
}
if ((cc=read(fd, query, MAX_QUERY_BUFFER))==-1)
{
- perror(s);
+ perror(fname);
close(fd);
- if (!f_arg)
- unlink(s);
+ if (!optarg)
+ unlink(fname);
break;
}
query[cc]='\0';
close(fd);
- if (!f_arg)
- unlink(s);
+ if (!optarg)
+ unlink(fname);
rightTrim(query);
if (query[strlen(query)-1]==';')
return 0;
break;
}
- case 'f':
- if (optarg)
- strcpy(settings->fieldSep,optarg);
- else
- strcpy(settings->fieldSep,DEFAULT_FIELD_SEP);
- break;
- case 'g': /* \g means send query */
- status = 0;
- break;
- case 'i': /* \i is include file */
- {
- FILE* fd;
-
- if (!optarg) {
- fprintf(stderr,"\\i must be followed by a file name\n");
- status = 1;
- break;
+ case 'f':
+ {
+ char *fs=DEFAULT_FIELD_SEP;
+ if (optarg)
+ fs=optarg;
+ if (settings->opt.fieldSep);
+ free(settings->opt.fieldSep);
+ if (!(settings->opt.fieldSep=dupstr(fs)))
+ {
+ perror("malloc");
+ exit(1);
}
-
- if ( (fd = fopen(optarg, "r")) == NULL)
- {
- fprintf(stderr,"file named %s could not be opened\n",optarg);
- status = 1;
- break;
- }
- MainLoop(&db, fd, settings);
- fclose(fd);
- status = 1;
+ if (!settings->quiet)
+ fprintf(stderr, "field separater changed to '%s'\n", settings->opt.fieldSep);
break;
- }
+ }
+ case 'g': /* \g means send query */
+ settings->gfname = optarg;
+ status = 0;
+ break;
case 'h':
{
char* cmd;
@@ -727,7 +789,7 @@ HandleSlashCmds(PGconn** db_ptr,
numCmds = numCmds - 1;
- if ( strcmp(cmd,"*") == 0 ) {
+ if (strcmp(cmd, "*") == 0 ) {
all_help=1;
}
@@ -748,74 +810,154 @@ HandleSlashCmds(PGconn** db_ptr,
if (i == numCmds && ! all_help)
printf("command not found, try \\h with no arguments to see available help\n");
}
- status = 1;
+ break;
+ }
+ case 'i': /* \i is include file */
+ {
+ FILE* fd;
+
+ if (!optarg) {
+ fprintf(stderr,"\\i must be followed by a file name\n");
+ break;
+ }
+
+ if ((fd = fopen(optarg, "r")) == NULL)
+ {
+ fprintf(stderr,"file named %s could not be opened\n",optarg);
+ break;
+ }
+ MainLoop(settings, fd);
+ fclose(fd);
break;
}
case 'l': /* \l is list database */
- listAllDbs(db,settings);
- status = 1;
+ listAllDbs(settings);
+ break;
+ case 'H':
+ if (toggle(settings, &settings->opt.html3, "HTML3.0 tablular output"))
+ settings->opt.standard = 0;
break;
case 'o':
- settings->queryFout = setFout(optarg);
+ setFout(settings, optarg);
break;
case 'p':
- if (query) {
- fputs(query, stdout);
- fputc('\n', stdout);
- status = 1;
- }
- break;
+ if (query)
+ {
+ fputs(query, stdout);
+ fputc('\n', stdout);
+ }
+ break;
case 'q': /* \q is quit */
status = 2;
break;
case 'r':
- query[0] = '\0';
- status = 1;
- break;
- case 's': /* \s is save history to a file */
- {
- char* fname;
-
- if (!optarg) {
- fprintf(stderr,"\\s must be followed by a file name\n");
- status = 1;
- break;
- }
-
- fname = optarg;
- if (write_history(fname) != 0)
+ {
+ FILE* fd;
+ static char *lastfile;
+ struct stat st, st2;
+ if (optarg)
+ {
+ if (lastfile)
+ free(lastfile);
+ lastfile=malloc(strlen(optarg+1));
+ if (!lastfile)
+ {
+ perror("malloc");
+ exit(1);
+ }
+ strcpy(lastfile, optarg);
+ } else if (!lastfile)
+ {
+ fprintf(stderr,"\\r must be followed by a file name initially\n");
+ break;
+ }
+ stat(lastfile, &st);
+ editFile(lastfile);
+ if ((stat(lastfile, &st2) == -1) || ((fd = fopen(lastfile, "r")) == NULL))
{
- fprintf(stderr,"cannot write history to %s\n",fname);
+ perror(lastfile);
+ break;
}
- status = 1;
+ if (st2.st_mtime==st.st_mtime)
+ {
+ if (!settings->quiet)
+ fprintf(stderr, "warning: %s not modified. query not executed\n", lastfile);
+ fclose(fd);
+ break;
+ }
+ MainLoop(settings, fd);
+ fclose(fd);
break;
}
- case 't':
- if ( settings->printHeader )
- settings->printHeader = 0;
+ case 's': /* \s is save history to a file */
+ if (!optarg)
+ optarg="/dev/tty";
+ if (write_history(optarg) != 0)
+ fprintf(stderr,"cannot write history to %s\n",optarg);
+ break;
+ case 'm': /* monitor like type-setting */
+ if (toggle(settings, &settings->opt.standard, "standard SQL separaters and padding"))
+ {
+ settings->opt.html3 = settings->opt.expanded = 0;
+ settings->opt.align = settings->opt.header = 1;
+ free(settings->opt.fieldSep);
+ settings->opt.fieldSep=dupstr("|");
+ if (!settings->quiet)
+ fprintf(stderr, "field separater changed to '%s'\n", settings->opt.fieldSep);
+ } else
+ {
+ free(settings->opt.fieldSep);
+ settings->opt.fieldSep=dupstr(DEFAULT_FIELD_SEP);
+ if (!settings->quiet)
+ fprintf(stderr, "field separater changed to '%s'\n", settings->opt.fieldSep);
+ }
+ break;
+ case 't': /* toggle headers */
+ toggle(settings, &settings->opt.header, "output headers");
+ break;
+ case 'T': /* define html <table ...> option */
+ if (settings->opt.tableOpt)
+ free(settings->opt.tableOpt);
+ if (!optarg)
+ settings->opt.tableOpt=NULL;
else
- settings->printHeader = 1;
- if (!settings->quiet)
- fprintf(stderr,"turning %s printing of field headers\n",
- (settings->printHeader) ? "on" : "off" );
+ if (!(settings->opt.tableOpt=dupstr(optarg)))
+ {
+ perror("malloc");
+ exit(1);
+ }
break;
+ case 'x':
+ toggle(settings, &settings->opt.expanded, "expanded table representation");
+ break;
+ case 'z': /* zorch buffer */
+ query[0]='\0';
+ if (!settings->quiet)
+ fprintf(stderr, "zorched current query buffer\n");
+ break;
case '!':
if (!optarg) {
- char sys[256];
+ char *sys;
char *shellName;
shellName = getenv("SHELL");
if (shellName == NULL)
shellName = DEFAULT_SHELL;
+ sys = malloc(strlen(shellName)+16);
+ if (!sys)
+ {
+ perror("malloc");
+ exit(1);
+ }
sprintf(sys,"exec %s", shellName);
system(sys);
+ free(sys);
}
else
system(optarg);
break;
default:
case '?': /* \? is help */
- slashUsage();
- status = 1;
+ slashUsage(settings);
break;
}
return status;
@@ -830,19 +972,14 @@ HandleSlashCmds(PGconn** db_ptr,
*db_ptr must be initialized and set
*/
+
int
-MainLoop(PGconn** db_ptr,
- FILE* source,
- PsqlSettings *settings)
+MainLoop(PsqlSettings *settings, FILE* source)
{
- char* prompt; /* readline prompt */
char* line; /* line of input*/
int len; /* length of the line */
char query[MAX_QUERY_BUFFER]; /* multi-line query storage */
- PGconn* db = *db_ptr;
- char* dbname = PQdb(db);
int exitStatus = 0;
-
int slashCmdStatus = 0;
/* slashCmdStatus can be:
0 - send currently constructed query to backend (i.e. we got a \g)
@@ -850,18 +987,21 @@ MainLoop(PGconn** db_ptr,
2 - terminate processing of this query entirely
*/
- int send_query = 0;
- int interactive;
+ bool sendQuery = 0;
+ bool querySent = 0;
+ bool interactive;
READ_ROUTINE GetNextLine;
- interactive = (source == stdin);
-
+ interactive = ((source == stdin) && !settings->notty);
+#define PROMPT "=> "
if (interactive) {
- prompt = malloc(strlen(dbname) + 10);
+ if (settings->prompt)
+ free(settings->prompt);
+ settings->prompt = malloc(strlen(PQdb(settings->db)) + strlen(PROMPT) + 1);
if (settings->quiet)
- prompt[0] = '\0';
+ settings->prompt[0] = '\0';
else
- sprintf(prompt,"%s=> ", dbname);
+ sprintf(settings->prompt,"%s%s", PQdb(settings->db), PROMPT);
if (settings->useReadline) {
using_history();
GetNextLine = gets_readline;
@@ -875,7 +1015,7 @@ MainLoop(PGconn** db_ptr,
query[0] = '\0';
/* main loop for getting queries and executing them */
- while ((line = GetNextLine(prompt, source)) != NULL)
+ while ((line = GetNextLine(settings->prompt, source)) != NULL)
{
exitStatus = 0;
line = rightTrim(line); /* remove whitespaces on the right, incl. \n's */
@@ -895,6 +1035,11 @@ MainLoop(PGconn** db_ptr,
free(line);
continue;
}
+ if (line[0] != '\\' && querySent)
+ {
+ query[0]='\0';
+ querySent = 0;
+ }
len = strlen(line);
@@ -903,34 +1048,31 @@ MainLoop(PGconn** db_ptr,
/* do the query immediately if we are doing single line queries
or if the last character is a semicolon */
- send_query = settings->singleLineMode || (line[len-1] == ';') ;
+ sendQuery = settings->singleLineMode || (line[len-1] == ';') ;
/* normally, \ commands have to be start the line,
but for backwards compatibility with monitor,
check for \g at the end of line */
- if (len > 2 && !send_query)
+ if (len > 2 && !sendQuery)
{
if (line[len-1]=='g' && line[len-2]=='\\')
{
- send_query = 1;
+ sendQuery = 1;
line[len-2]='\0';
}
}
/* slash commands have to be on their own line */
if (line[0] == '\\') {
- slashCmdStatus = HandleSlashCmds(db_ptr,
+ slashCmdStatus = HandleSlashCmds(settings,
line,
- &prompt,
- query,
- settings);
- db = *db_ptr; /* in case \c changed the database */
+ query);
if (slashCmdStatus == 1)
continue;
if (slashCmdStatus == 2)
break;
if (slashCmdStatus == 0)
- send_query = 1;
+ sendQuery = 1;
}
else
if (strlen(query) + len > MAX_QUERY_BUFFER)
@@ -946,30 +1088,29 @@ MainLoop(PGconn** db_ptr,
else
strcpy(query,line);
- if (send_query && query[0] != '\0')
+ if (sendQuery && query[0] != '\0')
{
/* echo the line read from the file,
unless we are in single_step mode, because single_step mode
will echo anyway */
- if (!interactive && !settings->singleStep)
- fprintf(stderr,"%s\n",query);
+ if (!interactive && !settings->singleStep && !settings->quiet)
+ fprintf(stderr,"%s\n", query);
- exitStatus = SendQuery(db, query, settings);
- query[0] = '\0';
+ exitStatus = SendQuery(settings, query);
+ querySent = 1;
}
free(line); /* free storage malloc'd by GetNextLine */
} /* while */
- return exitStatus;
+ return exitStatus;
}
int
main(int argc, char** argv)
{
extern char* optarg;
- extern int optind, opterr;
+ extern int optind;
- PGconn *db;
char* dbname = NULL;
char* host = NULL;
char* port = NULL;
@@ -980,31 +1121,27 @@ main(int argc, char** argv)
char* singleQuery = NULL;
- int listDatabases = 0 ;
+ bool listDatabases = 0 ;
int exitStatus = 0;
- int singleSlashCmd = 0;
+ bool singleSlashCmd = 0;
int c;
-
-#ifdef NOREADLINE
- settings.useReadline = 0;
-#else
- settings.useReadline = 1;
-#endif
-
- settings.quiet = 0;
- settings.fillAlign = 1;
- settings.printHeader = 1;
- settings.echoQuery = 0;
- settings.singleStep = 0;
- settings.singleLineMode = 0;
+ memset(&settings, 0, sizeof settings);
+ settings.opt.align = 1;
+ settings.opt.header = 1;
settings.queryFout = stdout;
- strcpy(settings.fieldSep, DEFAULT_FIELD_SEP);
+ settings.opt.fieldSep=dupstr(DEFAULT_FIELD_SEP);
+ if (!isatty(0) || !isatty(1))
+ settings.quiet = settings.notty = 1;
+ else
+#ifndef NOREADLINE
+ settings.useReadline = 1;
+#endif
- while ((c = getopt(argc, argv, "Aa:c:d:ef:F:lhH:nso:p:qST")) != EOF) {
+ while ((c = getopt(argc, argv, "Aa:c:d:ef:F:lh:Hnso:p:qStT:x")) != EOF) {
switch (c) {
case 'A':
- settings.fillAlign = 0;
+ settings.opt.align = 0;
break;
case 'a':
fe_setauthsvc(optarg, errbuf);
@@ -1025,20 +1162,23 @@ main(int argc, char** argv)
qfilename = optarg;
break;
case 'F':
- strncpy(settings.fieldSep,optarg,MAX_FIELD_SEP_LENGTH);
- break;
+ settings.opt.fieldSep=dupstr(optarg);
+ break;
case 'l':
listDatabases = 1;
break;
- case 'H':
+ case 'h':
host = optarg;
break;
+ case 'H':
+ settings.opt.html3 = 1;
+ break;
case 'n':
- settings.useReadline = 0;
- break;
+ settings.useReadline = 0;
+ break;
case 'o':
- settings.queryFout = setFout(optarg);
- break;
+ setFout(&settings, optarg);
+ break;
case 'p':
port = optarg;
break;
@@ -1051,10 +1191,15 @@ main(int argc, char** argv)
case 'S':
settings.singleLineMode = 1;
break;
+ case 't':
+ settings.opt.header = 0;
+ break;
case 'T':
- settings.printHeader = 0;
- break;
- case 'h':
+ settings.opt.tableOpt = dupstr(optarg);
+ break;
+ case 'x':
+ settings.opt.expanded = 0;
+ break;
default:
usage(argv[0]);
break;
@@ -1067,16 +1212,16 @@ main(int argc, char** argv)
if (listDatabases)
dbname = "template1";
- db = PQsetdb(host, port, NULL, NULL, dbname);
- dbname = PQdb(db);
+ settings.db = PQsetdb(host, port, NULL, NULL, dbname);
+ dbname = PQdb(settings.db);
- if (PQstatus(db) == CONNECTION_BAD) {
+ if (PQstatus(settings.db) == CONNECTION_BAD) {
fprintf(stderr,"Connection to database '%s' failed.\n", dbname);
- fprintf(stderr,"%s",PQerrorMessage(db));
+ fprintf(stderr,"%s",PQerrorMessage(settings.db));
exit(1);
}
if (listDatabases) {
- exit(listAllDbs(db,&settings));
+ exit(listAllDbs(&settings));
}
if (!settings.quiet && !singleQuery && !qfilename) {
@@ -1092,7 +1237,6 @@ main(int argc, char** argv)
/* read in a file full of queries instead of reading in queries
interactively */
char *line;
- char prompt[100];
if ( singleSlashCmd ) {
/* Not really a query, but "Do what I mean, not what I say." */
@@ -1102,24 +1246,25 @@ main(int argc, char** argv)
line = malloc(strlen(qfilename) + 5);
sprintf(line,"\\i %s", qfilename);
}
- HandleSlashCmds(&db, line, (char**)prompt, "", &settings);
+ HandleSlashCmds(&settings, line, "");
} else {
if (singleQuery) {
- exitStatus = SendQuery(db, singleQuery, &settings);
+ exitStatus = SendQuery(&settings, singleQuery);
}
else
- exitStatus = MainLoop(&db, stdin, &settings);
+ exitStatus = MainLoop(&settings, stdin);
}
- PQfinish(db);
+ PQfinish(settings.db);
return exitStatus;
}
+#define COPYBUFSIZ 8192
static void
-handleCopyOut(PGresult *res, int quiet)
+handleCopyOut(PGresult *res, bool quiet)
{
bool copydone = false;
char copybuf[COPYBUFSIZ];
@@ -1153,7 +1298,7 @@ handleCopyOut(PGresult *res, int quiet)
static void
-handleCopyIn(PGresult *res, int quiet)
+handleCopyIn(PGresult *res, bool quiet)
{
bool copydone = false;
bool firstload;
@@ -1212,24 +1357,38 @@ handleCopyIn(PGresult *res, int quiet)
PQendcopy(res->conn);
}
-
/* try to open fname and return a FILE*,
if it fails, use stdout, instead */
+
FILE*
-setFout(char *fname)
+setFout(PsqlSettings *ps, char *fname)
{
- FILE *queryFout;
-
- if (!fname)
- queryFout = stdout;
- else {
- queryFout = fopen(fname, "w");
- if (!queryFout) {
- perror(fname);
- queryFout = stdout;
+ if (ps->queryFout && ps->queryFout != stdout)
+ {
+ if (ps->pipe)
+ pclose(ps->queryFout);
+ else
+ fclose(ps->queryFout);
}
- }
-
- return queryFout;
+ if (!fname)
+ ps->queryFout = stdout;
+ else
+ {
+ if (*fname == '|')
+ {
+ signal(SIGPIPE, SIG_IGN);
+ ps->queryFout = popen(fname+1, "w");
+ ps->pipe = 1;
+ }
+ else
+ {
+ ps->queryFout = fopen(fname, "w");
+ ps->pipe = 0;
+ }
+ if (!ps->queryFout) {
+ perror(fname);
+ ps->queryFout = stdout;
+ }
+ }
+ return ps->queryFout;
}
-
commit 23c7ff0b3c38657081590430d08ef48bb5bde759
Author: Julian Assange <proff@suburbia.net>
Date: Thu Jul 25 06:21:11 1996 +0000
PQprint() routines. The older code is still there for historical
compatibility. There isn't much difference here against my previous
PQprint() code, except that you can add optional arguments to the
<table args> in html.
diff --git a/src/interfaces/libpq/fe-exec.c b/src/interfaces/libpq/fe-exec.c
index 4ba528e..fc2adef 100644
--- a/src/interfaces/libpq/fe-exec.c
+++ b/src/interfaces/libpq/fe-exec.c
@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.5 1996/07/23 03:35:13 scrappy Exp $
+ * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.6 1996/07/25 06:21:11 julian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -761,7 +761,7 @@ PQdisplayTuples(PGresult *res,
* PQprintTuples()
*
* This is the routine that prints out the tuples that
- * are returned from the backend.
+ * are returned from the backend.
* Right now all columns are of fixed length,
* this should be changed to allow wrap around for
* tuples values that are wider.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment