Commit be5bfd54 authored by Marc G. Fournier's avatar Marc G. Fournier

Put in a new FAQ

Merged in Dr. George's src/bin tree (possibly broke monitor/psql in process)
parent d1724d65
...@@ -7,24 +7,29 @@ ...@@ -7,24 +7,29 @@
# #
# #
# IDENTIFICATION # IDENTIFICATION
# $Header: /cvsroot/pgsql/src/bin/Makefile,v 1.1.1.1 1996/07/09 06:22:11 scrappy Exp $ # $Header: /cvsroot/pgsql/src/bin/Makefile,v 1.2 1996/07/23 03:01:58 scrappy Exp $
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
MKDIR=../mk
-include $(MKDIR)/../Makefile.global
# #
# C programs # C programs
# #
SUBDIR= monitor pg_id pg_version psql pg_dump SUBDIR= monitor pg_id pg_version psql pg_dump
ifeq ($(USE_TCL), true)
SUBDIR += pgtclsh
endif
# #
# Shell scripts # Shell scripts
# #
SUBDIR+= cleardbdir createdb createuser destroydb destroyuser initdb SUBDIR+= cleardbdir createdb createuser destroydb destroyuser initdb
#
# TCL/TK programs
#
ifeq ($(USE_TCL), true)
SUBDIR += pgtclsh
endif
include ../mk/postgres.subdir.mk include $(MKDIR)/postgres.subdir.mk
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
# #
# #
# IDENTIFICATION # IDENTIFICATION
# $Header: /cvsroot/pgsql/src/bin/initdb/Attic/initdb.sh,v 1.3 1996/07/20 07:33:36 scrappy Exp $ # $Header: /cvsroot/pgsql/src/bin/initdb/Attic/initdb.sh,v 1.4 1996/07/23 03:03:19 scrappy Exp $
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
...@@ -33,10 +33,6 @@ FILESDIR=$PGDATA/files ...@@ -33,10 +33,6 @@ FILESDIR=$PGDATA/files
PATH=$BINDIR:$PATH PATH=$BINDIR:$PATH
export PATH export PATH
# OPENLINK Added an fsync option to postmaster
# REQUIRES: pg95 compiled with -DOPENLINK_PATCHES, see README_OPENLINK
# FSYNC=-F
CMDNAME=`basename $0` CMDNAME=`basename $0`
# ---------------- # ----------------
...@@ -63,9 +59,9 @@ done ...@@ -63,9 +59,9 @@ done
# ---------------- # ----------------
if test "$debug" -eq 1 if test "$debug" -eq 1
then then
BACKENDARGS="-boot -C $FSYNC -d" BACKENDARGS="-boot -C -F -d"
else else
BACKENDARGS="-boot -C $FSYNC -Q" BACKENDARGS="-boot -C -F -Q"
fi fi
...@@ -220,9 +216,7 @@ then ...@@ -220,9 +216,7 @@ then
echo "vacuuming template1" echo "vacuuming template1"
fi fi
echo "vacuum" | postgres $FSYNC -Q template1 > /dev/null echo "vacuum" | postgres -F -Q template1 > /dev/null
fi fi
rm -f /tmp/create.$$ rm -f /tmp/create.$$
sync
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/bin/monitor/Attic/monitor.c,v 1.4 1996/07/23 02:26:41 scrappy Exp $ * $Header: /cvsroot/pgsql/src/bin/monitor/Attic/monitor.c,v 1.5 1996/07/23 03:03:24 scrappy Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
#ifndef WIN32 #ifndef WIN32
#include <unistd.h> #include <unistd.h>
#endif #endif
#ifdef PORTNAME_sparc_solaris #if defined(PORTNAME_sparc_solaris) || defined(PORTNAME_i386_solaris)
#include <netdb.h> /* for MAXHOSTNAMELEN on some */ #include <netdb.h> /* for MAXHOSTNAMELEN on some */
#endif #endif
#include <sys/types.h> #include <sys/types.h>
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <sys/param.h> /* for MAXHOSTNAMELEN on most */ #include <sys/param.h> /* for MAXHOSTNAMELEN on most */
#ifdef PORTNAME_sparc_solaris #if defined(PORTNAME_sparc_solaris) || defined(PORTNAME_i386_solaris)
#include <netdb.h> /* for MAXHOSTNAMELEN on some */ #include <netdb.h> /* for MAXHOSTNAMELEN on some */
#endif #endif
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <sys/param.h> /* for MAXHOSTNAMELEN on most */ #include <sys/param.h> /* for MAXHOSTNAMELEN on most */
#ifdef PORTNAME_sparc_solaris #if defined(PORTNAME_sparc_solaris) || defined(PORTNAME_i386_solaris)
#include <netdb.h> /* for MAXHOSTNAMELEN on some */ #include <netdb.h> /* for MAXHOSTNAMELEN on some */
#endif #endif
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
# #
# #
# IDENTIFICATION # IDENTIFICATION
# $Header: /cvsroot/pgsql/src/bin/pgtclsh/Attic/Makefile,v 1.1.1.1 1996/07/09 06:22:15 scrappy Exp $ # $Header: /cvsroot/pgsql/src/bin/pgtclsh/Attic/Makefile,v 1.2 1996/07/23 03:03:36 scrappy Exp $
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
...@@ -15,7 +15,7 @@ MKDIR= ../../mk ...@@ -15,7 +15,7 @@ MKDIR= ../../mk
include $(MKDIR)/postgres.mk include $(MKDIR)/postgres.mk
include ../Makefile.global include ../Makefile.global
CFLAGS+= -I$(TCL_INCDIR) -I$(TK_INCDIR) CFLAGS+= -I$(TCL_INCDIR) -I$(TK_INCDIR) -I$(X11_INCDIR) -I$(srcdir)/libpgtcl
# try to find libpgtcl.a in either directory # try to find libpgtcl.a in either directory
LIBPGTCL= -L$(srcdir)/libpgtcl/$(objdir) -L$(LIBDIR) -lpgtcl LIBPGTCL= -L$(srcdir)/libpgtcl/$(objdir) -L$(LIBDIR) -lpgtcl
...@@ -26,7 +26,7 @@ pgtclsh: $(objdir)/pgtclAppInit.o ...@@ -26,7 +26,7 @@ pgtclsh: $(objdir)/pgtclAppInit.o
pgtksh: $(objdir)/pgtkAppInit.o pgtksh: $(objdir)/pgtkAppInit.o
$(CC) $(CDEBUG) -o $(objdir)/$(@F) $(objdir)/pgtkAppInit.o \ $(CC) $(CDEBUG) -o $(objdir)/$(@F) $(objdir)/pgtkAppInit.o \
$(LIBPGTCL) $(LIBPQ) -L$(TCL_LIBDIR) -L$(TK_LIBDIR) \ $(LIBPGTCL) $(LIBPQ) -L$(TCL_LIBDIR) -L$(TK_LIBDIR) -L$(X11_LIBDIR) \
$(TK_LIB) $(TCL_LIB) -lX11 -lm $(LD_ADD) $(TK_LIB) $(TCL_LIB) -lX11 -lm $(LD_ADD)
install:: localobj pgtclsh pgtksh install:: localobj pgtclsh pgtksh
......
...@@ -109,6 +109,11 @@ Tcl_AppInit(interp) ...@@ -109,6 +109,11 @@ Tcl_AppInit(interp)
* then no user-specific startup file will be run under any conditions. * then no user-specific startup file will be run under any conditions.
*/ */
#if (TCL_MAJOR_VERSION <= 7) && (TCL_MINOR_VERSION < 5)
tcl_RcFileName = "~/.tclshrc"; tcl_RcFileName = "~/.tclshrc";
#else
Tcl_SetVar(interp, "tcl_rcFileName", "~/.tclshrc", TCL_GLOBAL_ONLY);
#endif
return TCL_OK; return TCL_OK;
} }
...@@ -112,6 +112,11 @@ Tcl_AppInit(interp) ...@@ -112,6 +112,11 @@ Tcl_AppInit(interp)
* then no user-specific startup file will be run under any conditions. * then no user-specific startup file will be run under any conditions.
*/ */
#if (TCL_MAJOR_VERSION <= 7) && (TCL_MINOR_VERSION < 5)
tcl_RcFileName = "~/.wishrc"; tcl_RcFileName = "~/.wishrc";
#else
Tcl_SetVar(interp, "tcl_rcFileName", "~/.wishrc", TCL_GLOBAL_ONLY);
#endif
return TCL_OK; return TCL_OK;
} }
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/bin/psql/Attic/psql.c,v 1.5 1996/07/20 08:44:45 scrappy Exp $ * $Header: /cvsroot/pgsql/src/bin/psql/Attic/psql.c,v 1.6 1996/07/23 03:03:43 scrappy Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -16,8 +16,8 @@ ...@@ -16,8 +16,8 @@
#include <signal.h> #include <signal.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h> #include <fcntl.h>
#include "libpq-fe.h" #include "libpq-fe.h"
#include "stringutils.h" #include "stringutils.h"
...@@ -32,57 +32,52 @@ extern char *readline(char *); /* in rlstubs.c */ ...@@ -32,57 +32,52 @@ extern char *readline(char *); /* in rlstubs.c */
#include "history.h" #include "history.h"
#else #else
#include <readline/readline.h> #include <readline/readline.h>
#include <readline/history.h> #include <history.h>
#endif #endif
#endif #endif
#define MAX_QUERY_BUFFER 20000 #define MAX_QUERY_BUFFER 20000
#define MAX_FIELD_SEP_LENGTH 40
#define COPYBUFSIZ 8192 #define COPYBUFSIZ 8192
#define DEFAULT_FIELD_SEP "|" #define DEFAULT_FIELD_SEP " "
#define DEFAULT_EDITOR "vi" #define DEFAULT_EDITOR "vi"
#define DEFAULT_SHELL "/bin/sh" #define DEFAULT_SHELL "/bin/sh"
typedef struct _psqlSettings { typedef struct _psqlSettings {
PGconn *db; /* connection to backend */ 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 */ FILE *queryFout; /* where to send the query results */
PQprintOpt opt; /* options to be passed to PQprint */ char fieldSep[MAX_FIELD_SEP_LENGTH]; /* field separator */
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; } PsqlSettings;
/* declarations for functions in this file */ /* declarations for functions in this file */
static void usage(char* progname); static void usage(char* progname);
static void slashUsage(); static void slashUsage();
static void handleCopyOut(PGresult *res, bool quiet); static void handleCopyOut(PGresult *res, int quiet);
static void handleCopyIn(PGresult *res, bool quiet); static void handleCopyIn(PGresult *res, int quiet);
static int tableList(PsqlSettings *ps, bool deep_tablelist); static int tableList(PGconn* conn, int deep_tablelist);
static int tableDesc(PsqlSettings *ps, char *table); static int tableDesc(PGconn* conn, char* table);
char* gets_noreadline(char* prompt, FILE* source); char* gets_noreadline(char* prompt, FILE* source);
char* gets_readline(char* prompt, FILE* source); char* gets_readline(char* prompt, FILE* source);
char* gets_fromFile(char* prompt, FILE* source); char* gets_fromFile(char* prompt, FILE* source);
int listAllDbs(PsqlSettings *settings); int listAllDbs(PGconn *db, PsqlSettings *settings);
int SendQuery(PsqlSettings *settings, char* query); int SendQuery(PGconn* db, char* query, PsqlSettings *settings);
int HandleSlashCmds(PsqlSettings *settings, int HandleSlashCmds(PGconn** db_ptr,
char *line, char *line,
char *query); char** prompt_ptr,
int MainLoop(PsqlSettings *settings, FILE *source); char *query,
/* probably should move this into libpq */ PsqlSettings *settings);
void PQprint(FILE *fp, int MainLoop(PGconn** db_ptr, FILE *source, PsqlSettings *settings);
PGresult *res, FILE* setFout(char *fname);
PQprintOpt *po
);
FILE* setFout(PsqlSettings *ps, char *fname);
/* /*
* usage * usage
...@@ -94,24 +89,22 @@ usage(char* progname) ...@@ -94,24 +89,22 @@ usage(char* progname)
{ {
fprintf(stderr,"Usage: %s [options] [dbname]\n",progname); fprintf(stderr,"Usage: %s [options] [dbname]\n",progname);
fprintf(stderr,"\t -a authsvc set authentication service\n"); fprintf(stderr,"\t -a authsvc set authentication service\n");
fprintf(stderr,"\t -A turn off alignment when printing out attributes\n"); fprintf(stderr,"\t -A turn off fill-justification when printing out attributes\n");
fprintf(stderr,"\t -c query run single query (slash commands too)\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 -d dbName specify database name\n");
fprintf(stderr,"\t -e echo the query sent to the backend\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 filename use file as a source of queries\n");
fprintf(stderr,"\t -F sep set the field separator (default is " ")\n"); fprintf(stderr,"\t -F sep set the field separator (default is " ")\n");
fprintf(stderr,"\t -h host set database server host\n"); fprintf(stderr,"\t -h help information\n");
fprintf(stderr,"\t -H turn on html3.0 table output\n"); fprintf(stderr,"\t -H host set database server host\n");
fprintf(stderr,"\t -l list available databases\n"); fprintf(stderr,"\t -l list available databases\n");
fprintf(stderr,"\t -n don't use readline library\n"); fprintf(stderr,"\t -n don't use readline library\n");
fprintf(stderr,"\t -o filename send output to filename or (|pipe)\n"); fprintf(stderr,"\t -o filename send output to filename\n");
fprintf(stderr,"\t -p port set port number\n"); fprintf(stderr,"\t -p port set port number\n");
fprintf(stderr,"\t -q run quietly (no messages, no prompts)\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 step mode (prompts for each query)\n");
fprintf(stderr,"\t -S single line mode (i.e. query terminated by newline)\n"); fprintf(stderr,"\t -S single line mode (i.e. query terminated by newline)\n");
fprintf(stderr,"\t -t turn off printing of attribute headers\n"); fprintf(stderr,"\t -T turn off printing of attribute names\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); exit(1);
} }
...@@ -120,60 +113,29 @@ usage(char* progname) ...@@ -120,60 +113,29 @@ usage(char* progname)
* print out usage for the backslash commands * print out usage for the backslash commands
*/ */
char *on(bool f)
{
return f? "on": "off";
}
static void static void
slashUsage(PsqlSettings *ps) slashUsage()
{ {
fprintf(stderr,"\t \\a -- toggle field-alignment (currenty %s)\n", on(ps->opt.align)); fprintf(stderr,"\t \\a -- toggle fill-justification of display of attributes\n");
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 [<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 \\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 \\e [<fname>] -- edit the current query buffer or <fname>\n");
fprintf(stderr,"\t \\f [<sep>] -- change field separater (currently '%s')\n", ps->opt.fieldSep); fprintf(stderr,"\t \\f <sep> -- change field separator\n");
fprintf(stderr,"\t \\g [<fname>] -- send query to backend [and place results in <fname>]\n"); fprintf(stderr,"\t \\g -- query to backend\n");
fprintf(stderr,"\t \\g |<cmd> -- send query to backend and pipe results into <cmd>\n"); fprintf(stderr,"\t \\h <command> -- help on syntax of sql commands\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 \\h * -- complete description of all sql commands\n");
fprintf(stderr,"\t \\H -- toggle html3 output (currently %s)\n", on(ps->opt.html3)); fprintf(stderr,"\t \\g -- send query to backend\n");
fprintf(stderr,"\t \\i <fname> -- read and execute queries from filename\n"); fprintf(stderr,"\t \\i <fname> -- read queries from filename\n");
fprintf(stderr,"\t \\l -- list all databases\n"); fprintf(stderr,"\t \\l -- list all databases\n");
fprintf(stderr,"\t \\o [<fname>] -- send query results to <fname> or stdout\n"); fprintf(stderr,"\t \\o [<fname>] -- send query results file named <fname> or stdout\n");
fprintf(stderr,"\t \\o |<cmd> -- pipe query results through <cmd>\n");
fprintf(stderr,"\t \\p -- print the current query buffer\n"); fprintf(stderr,"\t \\p -- print the current query buffer\n");
fprintf(stderr,"\t \\q -- quit\n"); fprintf(stderr,"\t \\q -- quit\n");
fprintf(stderr,"\t \\r [<fname>] -- edit <fname> then send contents to backend\n"); fprintf(stderr,"\t \\s [<fname>] -- save or print history\n");
fprintf(stderr,"\t \\s [<fname>] -- print history or save it in <fname>\n"); fprintf(stderr,"\t \\t -- toggle output field headers (defaults to on)\n");
fprintf(stderr,"\t \\S -- toggle standard sql type-setting (currently %s)\n", on(ps->opt.standard)); fprintf(stderr,"\t \\! [<cmd>] -- shell escape\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"); 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 * listAllDbs
* *
...@@ -182,37 +144,50 @@ PSQLexec(PsqlSettings *ps, char *query) ...@@ -182,37 +144,50 @@ PSQLexec(PsqlSettings *ps, char *query)
* *
* *
*/ */
int int
listAllDbs(PsqlSettings *ps) listAllDbs(PGconn *db, PsqlSettings *settings)
{ {
PGresult *results; PGresult *results;
char* query = "select * from pg_database;"; char* query = "select * from pg_database;";
if (!(results=PSQLexec(ps, query))) results = PQexec(db, query);
if (results == NULL) {
fprintf(stderr,"%s", PQerrorMessage(db));
return 1; return 1;
}
if (PQresultStatus(results) != PGRES_TUPLES_OK)
{
fprintf(stderr,"Unexpected error from executing: %s\n", query);
return 2;
}
else else
{ {
PQprint(ps->queryFout, PQdisplayTuples(results,
results, settings->queryFout,
&ps->opt); settings->fillAlign,
settings->fieldSep,
settings->printHeader,
settings->quiet);
PQclear(results); PQclear(results);
return 0; return 0;
} }
} }
/* /*
* tableList (PGconn* conn)
* *
* List The Database Tables * List The Database Tables
* returns 0 if all went well * returns 0 if all went well
* *
*/ */
int int
tableList (PsqlSettings *ps, bool deep_tablelist) tableList (PGconn* conn, int deep_tablelist)
{ {
char listbuf[256]; char listbuf[256];
int nColumns; int nColumns;
int i; int i;
char* ru;
char* rk; char* rk;
char* rr; char* rr;
...@@ -228,8 +203,17 @@ tableList (PsqlSettings *ps, bool deep_tablelist) ...@@ -228,8 +203,17 @@ tableList (PsqlSettings *ps, bool deep_tablelist)
add in the int4oideq function */ add in the int4oideq function */
strcat(listbuf," and usesysid = relowner"); strcat(listbuf," and usesysid = relowner");
strcat(listbuf," ORDER BY relname "); strcat(listbuf," ORDER BY relname ");
if (!(res=PSQLexec(ps, listbuf))) res = PQexec(conn,listbuf);
return -1; 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);
}
/* first, print out the attribute names */ /* first, print out the attribute names */
nColumns = PQntuples(res); nColumns = PQntuples(res);
...@@ -252,14 +236,14 @@ tableList (PsqlSettings *ps, bool deep_tablelist) ...@@ -252,14 +236,14 @@ tableList (PsqlSettings *ps, bool deep_tablelist)
PQclear(res); PQclear(res);
for (i=0; i < nColumns; i++) { for (i=0; i < nColumns; i++) {
tableDesc(ps, table[i]); tableDesc(conn,table[i]);
} }
free(table); free(table);
} }
else { else {
/* Display the information */ /* Display the information */
printf ("\nDatabase = %s\n", PQdb(ps->db)); printf ("\nDatabase = %s\n", PQdb(conn));
printf (" +------------------+----------------------------------+----------+\n"); printf (" +------------------+----------------------------------+----------+\n");
printf (" | Owner | Relation | Type |\n"); printf (" | Owner | Relation | Type |\n");
printf (" +------------------+----------------------------------+----------+\n"); printf (" +------------------+----------------------------------+----------+\n");
...@@ -288,7 +272,7 @@ tableList (PsqlSettings *ps, bool deep_tablelist) ...@@ -288,7 +272,7 @@ tableList (PsqlSettings *ps, bool deep_tablelist)
} }
/* /*
* Describe a table * Describe a table (PGconn* conn, char* table)
* *
* Describe the columns in a database table. * Describe the columns in a database table.
* returns 0 if all went well * returns 0 if all went well
...@@ -296,7 +280,7 @@ tableList (PsqlSettings *ps, bool deep_tablelist) ...@@ -296,7 +280,7 @@ tableList (PsqlSettings *ps, bool deep_tablelist)
* *
*/ */
int int
tableDesc (PsqlSettings *ps, char *table) tableDesc (PGconn* conn, char* table)
{ {
char descbuf[256]; char descbuf[256];
int nColumns; int nColumns;
...@@ -318,8 +302,16 @@ tableDesc (PsqlSettings *ps, char *table) ...@@ -318,8 +302,16 @@ tableDesc (PsqlSettings *ps, char *table)
strcat(descbuf," and a.attrelid = c.oid "); strcat(descbuf," and a.attrelid = c.oid ");
strcat(descbuf," and a.atttypid = t.oid "); strcat(descbuf," and a.atttypid = t.oid ");
strcat(descbuf," ORDER BY attnum "); strcat(descbuf," ORDER BY attnum ");
if (!(res = PSQLexec(ps, descbuf))) res = PQexec(conn,descbuf);
return -1; 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);
}
/* first, print out the attribute names */ /* first, print out the attribute names */
nColumns = PQntuples(res); nColumns = PQntuples(res);
if (nColumns > 0) if (nColumns > 0)
...@@ -329,9 +321,9 @@ tableDesc (PsqlSettings *ps, char *table) ...@@ -329,9 +321,9 @@ tableDesc (PsqlSettings *ps, char *table)
*/ */
printf ("\nTable = %s\n", table); printf ("\nTable = %s\n", table);
printf ("+----------------------------------+----------------------------------+--------+\n"); printf ("+----------------------------------+----------------------------------+-------+\n");
printf ("| Field | Type | Length |\n"); printf ("| Field | Type | Length|\n");
printf ("+----------------------------------+----------------------------------+--------+\n"); printf ("+----------------------------------+----------------------------------+-------+\n");
/* next, print out the instances */ /* next, print out the instances */
for (i=0; i < PQntuples(res); i++) { for (i=0; i < PQntuples(res); i++) {
...@@ -340,15 +332,15 @@ tableDesc (PsqlSettings *ps, char *table) ...@@ -340,15 +332,15 @@ tableDesc (PsqlSettings *ps, char *table)
rsize = atoi(PQgetvalue(res,i,3)); rsize = atoi(PQgetvalue(res,i,3));
if (strcmp(rtype, "text") == 0) { if (strcmp(rtype, "text") == 0) {
printf ("%-32.32s |", rtype); printf ("%-32.32s |", rtype);
printf ("%6s |", "var" ); printf ("%-6s |", "var" );
} }
else if (strcmp(rtype, "bpchar") == 0) { else if (strcmp(rtype, "bpchar") == 0) {
printf ("%-32.32s |", "char"); printf ("%-32.32s |", "char");
printf ("%6i |", rsize > 0 ? rsize - 4 : 0 ); printf ("%-6i |", rsize > 0 ? rsize - 4 : 0 );
} }
else if (strcmp(rtype, "varchar") == 0) { else if (strcmp(rtype, "varchar") == 0) {
printf ("%-32.32s |", rtype); printf ("%-32.32s |", rtype);
printf ("%6i |", rsize > 0 ? rsize - 4 : 0 ); printf ("%-6i |", rsize > 0 ? rsize - 4 : 0 );
} }
else { else {
/* array types start with an underscore */ /* array types start with an underscore */
...@@ -363,13 +355,13 @@ tableDesc (PsqlSettings *ps, char *table) ...@@ -363,13 +355,13 @@ tableDesc (PsqlSettings *ps, char *table)
free(newname); free(newname);
} }
if (rsize > 0) if (rsize > 0)
printf (" %6i |", rsize); printf ("%-6i |", rsize);
else else
printf (" %6s |", "var"); printf ("%-6s |", "var");
} }
printf("\n"); printf("\n");
} }
printf ("+----------------------------------+----------------------------------+--------+\n"); printf ("+----------------------------------+----------------------------------+-------+\n");
PQclear(res); PQclear(res);
return (0); return (0);
...@@ -404,6 +396,7 @@ gets_readline(char* prompt, FILE* source) ...@@ -404,6 +396,7 @@ gets_readline(char* prompt, FILE* source)
return (readline(prompt)); return (readline(prompt));
} }
/* /*
* gets_fromFile prompt source * gets_fromFile prompt source
* *
...@@ -433,12 +426,14 @@ gets_fromFile(char* prompt, FILE* source) ...@@ -433,12 +426,14 @@ gets_fromFile(char* prompt, FILE* source)
} }
/* /*
* SendQuery: send the query string to the backend * SendQuery:
SendQuery: send the query string to the backend
*
* return 0 if the query executed successfully * return 0 if the query executed successfully
* returns 1 otherwise * returns 1 otherwise
*/ */
int int
SendQuery(PsqlSettings *settings, char *query) SendQuery(PGconn* db, char* query, PsqlSettings *settings)
{ {
PGresult* results; PGresult* results;
PGnotify* notify; PGnotify* notify;
...@@ -459,41 +454,20 @@ SendQuery(PsqlSettings *settings, char *query) ...@@ -459,41 +454,20 @@ SendQuery(PsqlSettings *settings, char *query)
gets_fromFile("",stdin); gets_fromFile("",stdin);
} }
results = PQexec(settings->db, query); results = PQexec(db, query);
if (results == NULL) { if (results == NULL) {
fprintf(stderr,"%s",PQerrorMessage(settings->db)); fprintf(stderr,"%s",PQerrorMessage(db));
return 1; return 1;
} }
switch (PQresultStatus(results)) { switch (PQresultStatus(results)) {
case PGRES_TUPLES_OK: case PGRES_TUPLES_OK:
if (settings->gfname) PQdisplayTuples(results,
{ settings->queryFout,
PsqlSettings ps=*settings; settings->fillAlign,
FILE *fp; settings->fieldSep,
ps.queryFout=stdout; settings->printHeader,
fp=setFout(&ps, settings->gfname); settings->quiet);
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); PQclear(results);
break; break;
case PGRES_EMPTY_QUERY: case PGRES_EMPTY_QUERY:
...@@ -501,7 +475,7 @@ SendQuery(PsqlSettings *settings, char *query) ...@@ -501,7 +475,7 @@ SendQuery(PsqlSettings *settings, char *query)
break; break;
case PGRES_COMMAND_OK: case PGRES_COMMAND_OK:
if (!settings->quiet) if (!settings->quiet)
fprintf(stdout,"%s\n", PQcmdStatus(results)); fprintf(stdout,"%s\n",PQcmdStatus(results));
break; break;
case PGRES_COPY_OUT: case PGRES_COPY_OUT:
handleCopyOut(results, settings->quiet); handleCopyOut(results, settings->quiet);
...@@ -513,12 +487,13 @@ SendQuery(PsqlSettings *settings, char *query) ...@@ -513,12 +487,13 @@ SendQuery(PsqlSettings *settings, char *query)
case PGRES_FATAL_ERROR: case PGRES_FATAL_ERROR:
case PGRES_BAD_RESPONSE: case PGRES_BAD_RESPONSE:
status = 1; status = 1;
fprintf(stderr,"%s",PQerrorMessage(settings->db)); fprintf(stderr,"%s",PQerrorMessage(db));
break; break;
} }
/* check for asynchronous returns */ /* check for asynchronous returns */
notify = PQnotifies(settings->db); notify = PQnotifies(db);
if (notify) { if (notify) {
fprintf(stderr,"ASYNC NOTIFY of '%s' from backend pid '%d' received\n", fprintf(stderr,"ASYNC NOTIFY of '%s' from backend pid '%d' received\n",
notify->relname, notify->be_pid); notify->relname, notify->be_pid);
...@@ -529,71 +504,6 @@ SendQuery(PsqlSettings *settings, char *query) ...@@ -529,71 +504,6 @@ SendQuery(PsqlSettings *settings, char *query)
} }
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: HandleSlashCmds:
...@@ -609,161 +519,189 @@ decode(char *s) ...@@ -609,161 +519,189 @@ decode(char *s)
2 - terminate processing of this query entirely 2 - terminate processing of this query entirely
*/ */
int int
HandleSlashCmds(PsqlSettings *settings, HandleSlashCmds(PGconn** db_ptr,
char* line, char* line,
char *query) char** prompt_ptr,
char *query,
PsqlSettings *settings)
{ {
int status = 1; int status = 0;
PGconn* db = *db_ptr;
char* dbname = PQdb(db);
char *optarg = NULL; char *optarg = NULL;
int len; int len;
len = strlen(line); len = strlen(line);
if (len > 2) if (len > 2)
{
optarg = leftTrim(line+2); optarg = leftTrim(line+2);
decode(optarg);
}
switch (line[1]) switch (line[1])
{ {
case 'a': /* toggles to align fields on output */ case 'a': /* toggles to fill fields on output */
toggle(settings, &settings->opt.align, "field alignment"); if (settings->fillAlign)
break; settings->fillAlign = 0;
case 'c': /* define new caption */
if (settings->opt.caption)
free(settings->opt.caption);
if (!optarg)
settings->opt.caption=NULL;
else else
if (!(settings->opt.caption=dupstr(optarg))) settings->fillAlign = 1;
{ if (!settings->quiet)
perror("malloc"); fprintf(stderr,"turning %s fill-justification\n",
exit(1); (settings->fillAlign) ? "on" : "off" );
}
break; break;
case 'C': /* \C means connect to new database */ case 'c': /* \c means connect to new database */
{ {
char *dbname=PQdb(settings->db);
if (!optarg) { if (!optarg) {
fprintf(stderr,"\\c must be followed by a database name\n"); fprintf(stderr,"\\c must be followed by a database name\n");
status = 1;
break; break;
} }
{ if (strcmp(optarg, dbname) == 0) {
PGconn *olddb=settings->db; fprintf(stderr,"already connected to %s\n", dbname);
status = 1;
break;
}
else {
PGconn *olddb;
printf("closing connection to database: %s\n", dbname); printf("closing connection to database:%s\n", dbname);
settings->db = PQsetdb(PQhost(olddb), PQport(olddb), NULL, NULL, optarg); olddb = db;
db = PQsetdb(PQhost(olddb), PQport(olddb), NULL, NULL, optarg);
*db_ptr = db;
printf("connecting to new database: %s\n", optarg); printf("connecting to new database: %s\n", optarg);
if (PQstatus(settings->db) == CONNECTION_BAD) { if (PQstatus(db) == CONNECTION_BAD) {
fprintf(stderr,"%s\n", PQerrorMessage(settings->db)); fprintf(stderr,"%s\n", PQerrorMessage(db));
printf("reconnecting to %s\n", dbname); printf("reconnecting to %s\n", dbname);
settings->db = PQsetdb(PQhost(olddb), PQport(olddb), db = PQsetdb(PQhost(olddb), PQport(olddb),
NULL, NULL, dbname); NULL, NULL, dbname);
if (PQstatus(settings->db) == CONNECTION_BAD) { *db_ptr = db;
if (PQstatus(db) == CONNECTION_BAD) {
fprintf(stderr, fprintf(stderr,
"could not reconnect to %s. exiting\n", dbname); "could not reconnect to %s. exiting\n", dbname);
exit(2); exit(2);
} }
status = 1;
break; break;
} }
PQfinish(olddb); PQfinish(olddb);
free(settings->prompt); free(*prompt_ptr);
settings->prompt = malloc(strlen(PQdb(settings->db)) + 10); *prompt_ptr = malloc(strlen(optarg) + 10);
sprintf(settings->prompt,"%s=> ", PQdb(settings->db)); sprintf(*prompt_ptr,"%s=> ", optarg);
status = 1;
break; break;
} }
} }
break; break;
case 'd': /* \d describe tables or columns in a table */ case 'd': /* \d describe tables or columns in a table */
{
if (!optarg) { if (!optarg) {
tableList(settings, 0); tableList(db,0);
status = 1;
break; break;
} }
if (strcmp(optarg, "*") == 0 ) { if ( strcmp(optarg,"*") == 0 ) {
tableList(settings, 0); tableList(db, 0);
tableList(settings, 1); tableList(db, 1);
} }
else { else {
tableDesc(settings, optarg); tableDesc(db,optarg);
} }
status = 1;
break; break;
}
case 'e': case 'e':
{ {
char s[256];
int fd; int fd;
char tmp[64];
char *fname;
int cc;
int ql = strlen(query); int ql = strlen(query);
int f_arg = 0;
int cc;
if (optarg) if (optarg)
fname=optarg; {
f_arg = 1;
strcpy(s, optarg);
}
else else
{ {
sprintf(tmp, "/tmp/psql.%d.%d", getuid(), getpid()); sprintf(s, "/tmp/psql.%d.%d", geteuid(), getpid());
fname=tmp; unlink(s);
unlink(tmp);
if (ql) if (ql)
{ {
if ((fd=open(tmp, O_EXCL|O_CREAT|O_WRONLY, 0600))==-1) if ((fd=open(s, O_EXCL|O_CREAT|O_WRONLY, 0600))==-1)
{ {
perror(tmp); perror(s);
break; break;
} }
if (query[ql-1]!='\n') if (query[ql-1]!='\n')
strcat(query, "\n"); strcat(query, "\n");
if (write(fd, query, ql)!=ql) if (write(fd, query, ql)!=ql)
{ {
perror(tmp); perror(s);
close(fd); close(fd);
unlink(tmp); unlink(s);
break; break;
} }
close(fd); close(fd);
} }
} }
editFile(fname);
if ((fd=open(fname, O_RDONLY))==-1)
{ {
perror(fname); char sys[256];
if (!optarg) char *editorName;
unlink(fname); 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);
break; break;
} }
if ((cc=read(fd, query, MAX_QUERY_BUFFER))==-1) if ((cc=read(fd, query, MAX_QUERY_BUFFER))==-1)
{ {
perror(fname); perror(s);
close(fd); close(fd);
if (!optarg) if (!f_arg)
unlink(fname); unlink(s);
break; break;
} }
query[cc]='\0'; query[cc]='\0';
close(fd); close(fd);
if (!optarg) if (!f_arg)
unlink(fname); unlink(s);
rightTrim(query); rightTrim(query);
if (query[strlen(query)-1]==';') if (query[strlen(query)-1]==';')
return 0; return 0;
break; break;
} }
case 'f': case 'f':
{
char *fs=DEFAULT_FIELD_SEP;
if (optarg) if (optarg)
fs=optarg; strcpy(settings->fieldSep,optarg);
if (settings->opt.fieldSep); else
free(settings->opt.fieldSep); strcpy(settings->fieldSep,DEFAULT_FIELD_SEP);
if (!(settings->opt.fieldSep=dupstr(fs))) break;
case 'g': /* \g means send query */
status = 0;
break;
case 'i': /* \i is include file */
{ {
perror("malloc"); FILE* fd;
exit(1);
if (!optarg) {
fprintf(stderr,"\\i must be followed by a file name\n");
status = 1;
break;
} }
if (!settings->quiet)
fprintf(stderr, "field separater changed to '%s'\n", settings->opt.fieldSep); if ( (fd = fopen(optarg, "r")) == NULL)
{
fprintf(stderr,"file named %s could not be opened\n",optarg);
status = 1;
break; break;
} }
case 'g': /* \g means send query */ MainLoop(&db, fd, settings);
settings->gfname = optarg; fclose(fd);
status = 0; status = 1;
break; break;
}
case 'h': case 'h':
{ {
char* cmd; char* cmd;
...@@ -789,7 +727,7 @@ HandleSlashCmds(PsqlSettings *settings, ...@@ -789,7 +727,7 @@ HandleSlashCmds(PsqlSettings *settings,
numCmds = numCmds - 1; numCmds = numCmds - 1;
if (strcmp(cmd, "*") == 0 ) { if ( strcmp(cmd,"*") == 0 ) {
all_help=1; all_help=1;
} }
...@@ -810,143 +748,74 @@ HandleSlashCmds(PsqlSettings *settings, ...@@ -810,143 +748,74 @@ HandleSlashCmds(PsqlSettings *settings,
if (i == numCmds && ! all_help) if (i == numCmds && ! all_help)
printf("command not found, try \\h with no arguments to see available help\n"); printf("command not found, try \\h with no arguments to see available help\n");
} }
break; status = 1;
}
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; break;
} }
case 'l': /* \l is list database */ case 'l': /* \l is list database */
listAllDbs(settings); listAllDbs(db,settings);
break; status = 1;
case 'H':
if (toggle(settings, &settings->opt.html3, "HTML3.0 tablular output"))
settings->opt.standard = 0;
break; break;
case 'o': case 'o':
setFout(settings, optarg); settings->queryFout = setFout(optarg);
break; break;
case 'p': case 'p':
if (query) { if (query) {
fputs(query, stdout); fputs(query, stdout);
fputc('\n', stdout); fputc('\n', stdout);
status = 1;
} }
break; break;
case 'q': /* \q is quit */ case 'q': /* \q is quit */
status = 2; status = 2;
break; break;
case 'r': case 'r':
{ query[0] = '\0';
FILE* fd; status = 1;
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)) {
perror(lastfile);
break; break;
} case 's': /* \s is save history to a file */
if (st2.st_mtime==st.st_mtime) { {
if (!settings->quiet) char* fname;
fprintf(stderr, "warning: %s not modified. query not executed\n",
lastfile); if (!optarg) {
fclose(fd); fprintf(stderr,"\\s must be followed by a file name\n");
status = 1;
break; break;
} }
MainLoop(settings, fd);
fclose(fd); fname = optarg;
break; if (write_history(fname) != 0)
{
fprintf(stderr,"cannot write history to %s\n",fname);
} }
case 's': /* \s is save history to a file */ status = 1;
if (!optarg) optarg="/dev/tty";
if (write_history(optarg) != 0)
fprintf(stderr,"cannot write history to %s\n",optarg);
break; break;
case 'S': /* standard SQL output */
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':
case 't': /* toggle headers */ if ( settings->printHeader )
toggle(settings, &settings->opt.header, "output headers"); settings->printHeader = 0;
break;
case 'T': /* define html <table ...> option */
if (settings->opt.tableOpt) free(settings->opt.tableOpt);
if (!optarg) settings->opt.tableOpt=NULL;
else else
if (!(settings->opt.tableOpt=dupstr(optarg))) { settings->printHeader = 1;
perror("malloc"); if (!settings->quiet)
exit(1); fprintf(stderr,"turning %s printing of field headers\n",
} (settings->printHeader) ? "on" : "off" );
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; break;
case '!': case '!':
if (!optarg) { if (!optarg) {
char *sys; char sys[256];
char *shellName; char *shellName;
shellName = getenv("SHELL"); shellName = getenv("SHELL");
if (shellName == NULL) shellName = DEFAULT_SHELL; if (shellName == NULL)
sys = malloc(strlen(shellName)+16); shellName = DEFAULT_SHELL;
if (!sys) {
perror("malloc");
exit(1);
}
sprintf(sys,"exec %s", shellName); sprintf(sys,"exec %s", shellName);
system(sys); system(sys);
free(sys); }
} else system(optarg); else
system(optarg);
break; break;
default: default:
case '?': /* \? is help */ case '?': /* \? is help */
slashUsage(settings); slashUsage();
status = 1;
break; break;
} }
return status; return status;
...@@ -961,14 +830,19 @@ HandleSlashCmds(PsqlSettings *settings, ...@@ -961,14 +830,19 @@ HandleSlashCmds(PsqlSettings *settings,
*db_ptr must be initialized and set *db_ptr must be initialized and set
*/ */
int int
MainLoop(PsqlSettings *settings, FILE* source) MainLoop(PGconn** db_ptr,
FILE* source,
PsqlSettings *settings)
{ {
char* prompt; /* readline prompt */
char* line; /* line of input*/ char* line; /* line of input*/
int len; /* length of the line */ int len; /* length of the line */
char query[MAX_QUERY_BUFFER]; /* multi-line query storage */ char query[MAX_QUERY_BUFFER]; /* multi-line query storage */
PGconn* db = *db_ptr;
char* dbname = PQdb(db);
int exitStatus = 0; int exitStatus = 0;
int slashCmdStatus = 0; int slashCmdStatus = 0;
/* slashCmdStatus can be: /* slashCmdStatus can be:
0 - send currently constructed query to backend (i.e. we got a \g) 0 - send currently constructed query to backend (i.e. we got a \g)
...@@ -976,21 +850,18 @@ MainLoop(PsqlSettings *settings, FILE* source) ...@@ -976,21 +850,18 @@ MainLoop(PsqlSettings *settings, FILE* source)
2 - terminate processing of this query entirely 2 - terminate processing of this query entirely
*/ */
bool sendQuery = 0; int send_query = 0;
bool querySent = 0; int interactive;
bool interactive;
READ_ROUTINE GetNextLine; READ_ROUTINE GetNextLine;
interactive = ((source == stdin) && !settings->notty); interactive = (source == stdin);
#define PROMPT "=> "
if (interactive) { if (interactive) {
if (settings->prompt) prompt = malloc(strlen(dbname) + 10);
free(settings->prompt);
settings->prompt = malloc(strlen(PQdb(settings->db)) + strlen(PROMPT) + 1);
if (settings->quiet) if (settings->quiet)
settings->prompt[0] = '\0'; prompt[0] = '\0';
else else
sprintf(settings->prompt,"%s%s", PQdb(settings->db), PROMPT); sprintf(prompt,"%s=> ", dbname);
if (settings->useReadline) { if (settings->useReadline) {
using_history(); using_history();
GetNextLine = gets_readline; GetNextLine = gets_readline;
...@@ -1004,7 +875,7 @@ MainLoop(PsqlSettings *settings, FILE* source) ...@@ -1004,7 +875,7 @@ MainLoop(PsqlSettings *settings, FILE* source)
query[0] = '\0'; query[0] = '\0';
/* main loop for getting queries and executing them */ /* main loop for getting queries and executing them */
while ((line = GetNextLine(settings->prompt, source)) != NULL) while ((line = GetNextLine(prompt, source)) != NULL)
{ {
exitStatus = 0; exitStatus = 0;
line = rightTrim(line); /* remove whitespaces on the right, incl. \n's */ line = rightTrim(line); /* remove whitespaces on the right, incl. \n's */
...@@ -1024,11 +895,6 @@ MainLoop(PsqlSettings *settings, FILE* source) ...@@ -1024,11 +895,6 @@ MainLoop(PsqlSettings *settings, FILE* source)
free(line); free(line);
continue; continue;
} }
if (line[0] != '\\' && querySent)
{
query[0]='\0';
querySent = 0;
}
len = strlen(line); len = strlen(line);
...@@ -1037,31 +903,34 @@ MainLoop(PsqlSettings *settings, FILE* source) ...@@ -1037,31 +903,34 @@ MainLoop(PsqlSettings *settings, FILE* source)
/* do the query immediately if we are doing single line queries /* do the query immediately if we are doing single line queries
or if the last character is a semicolon */ or if the last character is a semicolon */
sendQuery = settings->singleLineMode || (line[len-1] == ';') ; send_query = settings->singleLineMode || (line[len-1] == ';') ;
/* normally, \ commands have to be start the line, /* normally, \ commands have to be start the line,
but for backwards compatibility with monitor, but for backwards compatibility with monitor,
check for \g at the end of line */ check for \g at the end of line */
if (len > 2 && !sendQuery) if (len > 2 && !send_query)
{ {
if (line[len-1]=='g' && line[len-2]=='\\') if (line[len-1]=='g' && line[len-2]=='\\')
{ {
sendQuery = 1; send_query = 1;
line[len-2]='\0'; line[len-2]='\0';
} }
} }
/* slash commands have to be on their own line */ /* slash commands have to be on their own line */
if (line[0] == '\\') { if (line[0] == '\\') {
slashCmdStatus = HandleSlashCmds(settings, slashCmdStatus = HandleSlashCmds(db_ptr,
line, line,
query); &prompt,
query,
settings);
db = *db_ptr; /* in case \c changed the database */
if (slashCmdStatus == 1) if (slashCmdStatus == 1)
continue; continue;
if (slashCmdStatus == 2) if (slashCmdStatus == 2)
break; break;
if (slashCmdStatus == 0) if (slashCmdStatus == 0)
sendQuery = 1; send_query = 1;
} }
else else
if (strlen(query) + len > MAX_QUERY_BUFFER) if (strlen(query) + len > MAX_QUERY_BUFFER)
...@@ -1077,16 +946,16 @@ MainLoop(PsqlSettings *settings, FILE* source) ...@@ -1077,16 +946,16 @@ MainLoop(PsqlSettings *settings, FILE* source)
else else
strcpy(query,line); strcpy(query,line);
if (sendQuery && query[0] != '\0') if (send_query && query[0] != '\0')
{ {
/* echo the line read from the file, /* echo the line read from the file,
unless we are in single_step mode, because single_step mode unless we are in single_step mode, because single_step mode
will echo anyway */ will echo anyway */
if (!interactive && !settings->singleStep && !settings->quiet) if (!interactive && !settings->singleStep)
fprintf(stderr,"%s\n", query); fprintf(stderr,"%s\n",query);
exitStatus = SendQuery(settings, query); exitStatus = SendQuery(db, query, settings);
querySent = 1; query[0] = '\0';
} }
free(line); /* free storage malloc'd by GetNextLine */ free(line); /* free storage malloc'd by GetNextLine */
...@@ -1098,8 +967,9 @@ int ...@@ -1098,8 +967,9 @@ int
main(int argc, char** argv) main(int argc, char** argv)
{ {
extern char* optarg; extern char* optarg;
extern int optind; extern int optind, opterr;
PGconn *db;
char* dbname = NULL; char* dbname = NULL;
char* host = NULL; char* host = NULL;
char* port = NULL; char* port = NULL;
...@@ -1110,27 +980,31 @@ main(int argc, char** argv) ...@@ -1110,27 +980,31 @@ main(int argc, char** argv)
char* singleQuery = NULL; char* singleQuery = NULL;
bool listDatabases = 0 ; int listDatabases = 0 ;
int exitStatus = 0; int exitStatus = 0;
bool singleSlashCmd = 0; int singleSlashCmd = 0;
int c; int c;
memset(&settings, 0, sizeof settings);
settings.opt.align = 1; #ifdef NOREADLINE
settings.opt.header = 1; settings.useReadline = 0;
settings.queryFout = stdout; #else
settings.opt.fieldSep=dupstr(DEFAULT_FIELD_SEP);
if (!isatty(0) || !isatty(1))
settings.quiet = settings.notty = 1;
else
#ifndef NOREADLINE
settings.useReadline = 1; settings.useReadline = 1;
#endif #endif
while ((c = getopt(argc, argv, "Aa:c:d:ef:F:lhH:nso:p:qStTx")) != EOF) { settings.quiet = 0;
settings.fillAlign = 1;
settings.printHeader = 1;
settings.echoQuery = 0;
settings.singleStep = 0;
settings.singleLineMode = 0;
settings.queryFout = stdout;
strcpy(settings.fieldSep, DEFAULT_FIELD_SEP);
while ((c = getopt(argc, argv, "Aa:c:d:ef:F:lhH:nso:p:qST")) != EOF) {
switch (c) { switch (c) {
case 'A': case 'A':
settings.opt.align = 0; settings.fillAlign = 0;
break; break;
case 'a': case 'a':
fe_setauthsvc(optarg, errbuf); fe_setauthsvc(optarg, errbuf);
...@@ -1151,22 +1025,19 @@ main(int argc, char** argv) ...@@ -1151,22 +1025,19 @@ main(int argc, char** argv)
qfilename = optarg; qfilename = optarg;
break; break;
case 'F': case 'F':
settings.opt.fieldSep=dupstr(optarg); strncpy(settings.fieldSep,optarg,MAX_FIELD_SEP_LENGTH);
break; break;
case 'l': case 'l':
listDatabases = 1; listDatabases = 1;
break; break;
case 'h':
host = optarg;
break;
case 'H': case 'H':
settings.opt.html3 = 1; host = optarg;
break; break;
case 'n': case 'n':
settings.useReadline = 0; settings.useReadline = 0;
break; break;
case 'o': case 'o':
setFout(&settings, optarg); settings.queryFout = setFout(optarg);
break; break;
case 'p': case 'p':
port = optarg; port = optarg;
...@@ -1180,15 +1051,10 @@ main(int argc, char** argv) ...@@ -1180,15 +1051,10 @@ main(int argc, char** argv)
case 'S': case 'S':
settings.singleLineMode = 1; settings.singleLineMode = 1;
break; break;
case 't':
settings.opt.header = 0;
break;
case 'T': case 'T':
settings.opt.tableOpt = dupstr(optarg); settings.printHeader = 0;
break;
case 'x':
settings.opt.expanded = 0;
break; break;
case 'h':
default: default:
usage(argv[0]); usage(argv[0]);
break; break;
...@@ -1201,16 +1067,16 @@ main(int argc, char** argv) ...@@ -1201,16 +1067,16 @@ main(int argc, char** argv)
if (listDatabases) if (listDatabases)
dbname = "template1"; dbname = "template1";
settings.db = PQsetdb(host, port, NULL, NULL, dbname); db = PQsetdb(host, port, NULL, NULL, dbname);
dbname = PQdb(settings.db); dbname = PQdb(db);
if (PQstatus(settings.db) == CONNECTION_BAD) { if (PQstatus(db) == CONNECTION_BAD) {
fprintf(stderr,"Connection to database '%s' failed.\n", dbname); fprintf(stderr,"Connection to database '%s' failed.\n", dbname);
fprintf(stderr,"%s",PQerrorMessage(settings.db)); fprintf(stderr,"%s",PQerrorMessage(db));
exit(1); exit(1);
} }
if (listDatabases) { if (listDatabases) {
exit(listAllDbs(&settings)); exit(listAllDbs(db,&settings));
} }
if (!settings.quiet && !singleQuery && !qfilename) { if (!settings.quiet && !singleQuery && !qfilename) {
...@@ -1226,6 +1092,7 @@ main(int argc, char** argv) ...@@ -1226,6 +1092,7 @@ main(int argc, char** argv)
/* read in a file full of queries instead of reading in queries /* read in a file full of queries instead of reading in queries
interactively */ interactively */
char *line; char *line;
char prompt[100];
if ( singleSlashCmd ) { if ( singleSlashCmd ) {
/* Not really a query, but "Do what I mean, not what I say." */ /* Not really a query, but "Do what I mean, not what I say." */
...@@ -1235,25 +1102,24 @@ main(int argc, char** argv) ...@@ -1235,25 +1102,24 @@ main(int argc, char** argv)
line = malloc(strlen(qfilename) + 5); line = malloc(strlen(qfilename) + 5);
sprintf(line,"\\i %s", qfilename); sprintf(line,"\\i %s", qfilename);
} }
HandleSlashCmds(&settings, line, ""); HandleSlashCmds(&db, line, (char**)prompt, "", &settings);
} else { } else {
if (singleQuery) { if (singleQuery) {
exitStatus = SendQuery(&settings, singleQuery); exitStatus = SendQuery(db, singleQuery, &settings);
} }
else else
exitStatus = MainLoop(&settings, stdin); exitStatus = MainLoop(&db, stdin, &settings);
} }
PQfinish(settings.db); PQfinish(db);
return exitStatus; return exitStatus;
} }
#define COPYBUFSIZ 8192
static void static void
handleCopyOut(PGresult *res, bool quiet) handleCopyOut(PGresult *res, int quiet)
{ {
bool copydone = false; bool copydone = false;
char copybuf[COPYBUFSIZ]; char copybuf[COPYBUFSIZ];
...@@ -1287,7 +1153,7 @@ handleCopyOut(PGresult *res, bool quiet) ...@@ -1287,7 +1153,7 @@ handleCopyOut(PGresult *res, bool quiet)
static void static void
handleCopyIn(PGresult *res, bool quiet) handleCopyIn(PGresult *res, int quiet)
{ {
bool copydone = false; bool copydone = false;
bool firstload; bool firstload;
...@@ -1346,38 +1212,24 @@ handleCopyIn(PGresult *res, bool quiet) ...@@ -1346,38 +1212,24 @@ handleCopyIn(PGresult *res, bool quiet)
PQendcopy(res->conn); PQendcopy(res->conn);
} }
/* try to open fname and return a FILE*, /* try to open fname and return a FILE*,
if it fails, use stdout, instead */ if it fails, use stdout, instead */
FILE* FILE*
setFout(PsqlSettings *ps, char *fname) setFout(char *fname)
{ {
if (ps->queryFout && ps->queryFout != stdout) FILE *queryFout;
{
if (ps->pipe)
pclose(ps->queryFout);
else
fclose(ps->queryFout);
}
if (!fname) if (!fname)
ps->queryFout = stdout; queryFout = stdout;
else else {
{ queryFout = fopen(fname, "w");
if (*fname == '|') if (!queryFout) {
{
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); perror(fname);
ps->queryFout = stdout; queryFout = stdout;
} }
} }
return ps->queryFout;
return queryFout;
} }
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