1 /*-------------------------------------------------------------------------
4 * an interactive front-end to postgres95
6 * Copyright (c) 1996, Regents of the University of California
10 * $Header: /cvsroot/pgsql/src/bin/psql/Attic/psql.c,v 1.18 1996/08/14 04:56:48 scrappy Exp $
12 *-------------------------------------------------------------------------
17 #include <sys/types.h>
22 #include "stringutils.h"
27 extern char *readline(char *); /* in rlstubs.c */
29 /* from the GNU readline library */
34 #include <readline/readline.h>
35 #include <readline/history.h>
39 #define MAX_QUERY_BUFFER 20000
41 #define COPYBUFSIZ 8192
43 #define DEFAULT_FIELD_SEP "|"
44 #define DEFAULT_EDITOR "vi"
45 #define DEFAULT_SHELL "/bin/sh"
47 typedef struct _psqlSettings {
48 PGconn *db; /* connection to backend */
49 FILE *queryFout; /* where to send the query results */
50 PQprintOpt opt; /* options to be passed to PQprint */
51 char *prompt; /* prompt to display */
52 char *gfname; /* one-shot file output argument for \g */
53 bool notty; /* input or output is not a tty */
54 bool pipe; /* queryFout is from a popen() */
55 bool echoQuery; /* echo the query before sending it */
56 bool quiet; /* run quietly, no messages, no promt */
57 bool singleStep; /* prompt before for each query */
58 bool singleLineMode; /* query terminated by newline */
59 bool useReadline; /* use libreadline routines */
62 /* declarations for functions in this file */
63 static void usage(char *progname);
64 static void slashUsage();
65 static void handleCopyOut(PGresult *res, bool quiet);
66 static void handleCopyIn(PGresult *res, bool quiet);
67 static int tableList(PsqlSettings *ps, bool deep_tablelist);
68 static int tableDesc(PsqlSettings *ps, char *table);
70 char *gets_noreadline(char *prompt, FILE *source);
71 char *gets_readline(char *prompt, FILE *source);
72 char *gets_fromFile(char *prompt, FILE *source);
73 int listAllDbs(PsqlSettings *settings);
74 int SendQuery(PsqlSettings *settings, char *query);
75 int HandleSlashCmds(PsqlSettings *settings,
78 int MainLoop(PsqlSettings *settings, FILE *source);
79 /* probably should move this into libpq */
80 void PQprint(FILE *fp,
85 FILE *setFout(PsqlSettings *ps, char *fname);
89 * print out usage for command line arguments
95 fprintf(stderr,"Usage: %s [options] [dbname]\n",progname);
96 fprintf(stderr,"\t -a authsvc set authentication service\n");
97 fprintf(stderr,"\t -A turn off alignment when printing out attributes\n");
98 fprintf(stderr,"\t -c query run single query (slash commands too)\n");
99 fprintf(stderr,"\t -d dbName specify database name\n");
100 fprintf(stderr,"\t -e echo the query sent to the backend\n");
101 fprintf(stderr,"\t -f filename use file as a source of queries\n");
102 fprintf(stderr,"\t -F sep set the field separator (default is " ")\n");
103 fprintf(stderr,"\t -h host set database server host\n");
104 fprintf(stderr,"\t -H turn on html3.0 table output\n");
105 fprintf(stderr,"\t -l list available databases\n");
106 fprintf(stderr,"\t -n don't use readline library\n");
107 fprintf(stderr,"\t -o filename send output to filename or (|pipe)\n");
108 fprintf(stderr,"\t -p port set port number\n");
109 fprintf(stderr,"\t -q run quietly (no messages, no prompts)\n");
110 fprintf(stderr,"\t -s single step mode (prompts for each query)\n");
111 fprintf(stderr,"\t -S single line mode (i.e. query terminated by newline)\n");
112 fprintf(stderr,"\t -t turn off printing of headings and row count\n");
113 fprintf(stderr,"\t -T html set html3.0 table command options (cf. -H)\n");
114 fprintf(stderr,"\t -x turn on expanded output (field names on left)\n");
120 * print out usage for the backslash commands
125 return f? "on": "off";
129 slashUsage(PsqlSettings *ps)
131 fprintf(stderr,"\t \\? -- help\n");
132 fprintf(stderr,"\t \\a -- toggle field-alignment (currenty %s)\n", on(ps->opt.align));
133 fprintf(stderr,"\t \\C [<captn>] -- set html3 caption (currently '%s')\n", ps->opt.caption? ps->opt.caption: "");
134 fprintf(stderr,"\t \\c <dbname> -- connect to new database (currently '%s')\n", PQdb(ps->db));
135 fprintf(stderr,"\t \\d [<table>] -- list tables in database or columns in <table>,* for all\n");
136 fprintf(stderr,"\t \\e [<fname>] -- edit the current query buffer or <fname>, \\E execute too\n");
137 fprintf(stderr,"\t \\f [<sep>] -- change field separater (currently '%s')\n", ps->opt.fieldSep);
138 fprintf(stderr,"\t \\g [<fname>] -- send query to backend [and place results in <fname>]\n");
139 fprintf(stderr,"\t \\g |<cmd> -- send query to backend and pipe results into <cmd>\n");
140 fprintf(stderr,"\t \\h [<cmd>] -- help on syntax of sql commands, * for all commands\n");
141 fprintf(stderr,"\t \\H -- toggle html3 output (currently %s)\n", on(ps->opt.html3));
142 fprintf(stderr,"\t \\i <fname> -- read and execute queries from filename\n");
143 fprintf(stderr,"\t \\l -- list all databases\n");
144 fprintf(stderr,"\t \\m -- toggle monitor-like table display (currently %s)\n", on(ps->opt.standard));
145 fprintf(stderr,"\t \\o [<fname>] -- send all query results to <fname> or stdout\n");
146 fprintf(stderr,"\t \\o |<cmd> -- pipe all query results through <cmd>\n");
147 fprintf(stderr,"\t \\p -- print the current query buffer\n");
148 fprintf(stderr,"\t \\q -- quit\n");
149 fprintf(stderr,"\t \\r -- reset(clear) the query buffer\n");
150 fprintf(stderr,"\t \\s [<fname>] -- print history or save it in <fname>\n");
151 fprintf(stderr,"\t \\t -- toggle table headings and row count (currently %s)\n", on(ps->opt.header));
152 fprintf(stderr,"\t \\T [<html>] -- set html3.0 <table ...> options (currently '%s')\n", ps->opt.tableOpt? ps->opt.tableOpt: "");
153 fprintf(stderr,"\t \\x -- toggle expanded output (currently %s)\n", on(ps->opt.expanded));
154 fprintf(stderr,"\t \\! [<cmd>] -- shell escape or command\n");
158 PSQLexec(PsqlSettings *ps, char *query)
160 PGresult *res = PQexec(ps->db, query);
162 fputs(PQerrorMessage(ps->db), stderr);
165 if (PQresultStatus(res)==PGRES_COMMAND_OK ||
166 PQresultStatus(res)==PGRES_TUPLES_OK)
169 fputs(PQerrorMessage(ps->db), stderr);
177 * list all the databases in the system
178 * returns 0 if all went well
184 listAllDbs(PsqlSettings *ps)
187 char *query = "select * from pg_database;";
189 if (!(results=PSQLexec(ps, query)))
193 PQprint(ps->queryFout,
203 * List The Database Tables
204 * returns 0 if all went well
208 tableList (PsqlSettings *ps, bool deep_tablelist)
219 strcat(listbuf,"SELECT usename, relname, relkind, relhasrules");
220 strcat(listbuf," FROM pg_class, pg_user ");
221 strcat(listbuf,"WHERE ( relkind = 'r' OR relkind = 'i') ");
222 strcat(listbuf," and relname !~ '^pg_'");
223 strcat(listbuf," and relname !~ '^Inv[0-9]+'");
224 /* the usesysid = relowner won't work on stock 1.0 dbs, need to
225 add in the int4oideq function */
226 strcat(listbuf," and usesysid = relowner");
227 strcat(listbuf," ORDER BY relname ");
228 if (!(res=PSQLexec(ps, listbuf)))
231 /* first, print out the attribute names */
232 nColumns = PQntuples(res);
235 if ( deep_tablelist ) {
236 /* describe everything here */
238 table = (char**)malloc(nColumns * sizeof(char*));
242 /* load table table */
243 for (i=0; i < nColumns; i++) {
244 table[i] = (char *) malloc(PQgetlength(res,i,1) * sizeof(char) + 1);
245 if ( table[i] == NULL )
247 strcpy(table[i],PQgetvalue(res,i,1));
251 for (i=0; i < nColumns; i++) {
252 tableDesc(ps, table[i]);
257 /* Display the information */
259 printf ("\nDatabase = %s\n", PQdb(ps->db));
260 printf (" +------------------+----------------------------------+----------+\n");
261 printf (" | Owner | Relation | Type |\n");
262 printf (" +------------------+----------------------------------+----------+\n");
264 /* next, print out the instances */
265 for (i=0; i < PQntuples(res); i++) {
266 printf (" | %-16.16s", PQgetvalue(res,i,0));
267 printf (" | %-32.32s | ", PQgetvalue(res,i,1));
268 rk = PQgetvalue(res,i,2);
269 rr = PQgetvalue(res,i,3);
270 if (strcmp(rk, "r") == 0)
271 printf ("%-8.8s |", (rr[0] == 't') ? "view?" : "table" );
273 printf ("%-8.8s |", "index");
276 printf (" +------------------+----------------------------------+----------+\n");
282 fprintf (stderr, "Couldn't find any tables!\n");
290 * Describe the columns in a database table.
291 * returns 0 if all went well
296 tableDesc (PsqlSettings *ps, char *table)
306 /* Build the query */
309 strcat(descbuf,"SELECT a.attnum, a.attname, t.typname, a.attlen");
310 strcat(descbuf," FROM pg_class c, pg_attribute a, pg_type t ");
311 strcat(descbuf," WHERE c.relname = '");
312 strcat(descbuf,table);
314 strcat(descbuf," and a.attnum > 0 ");
315 strcat(descbuf," and a.attrelid = c.oid ");
316 strcat(descbuf," and a.atttypid = t.oid ");
317 strcat(descbuf," ORDER BY attnum ");
318 if (!(res = PSQLexec(ps, descbuf)))
320 /* first, print out the attribute names */
321 nColumns = PQntuples(res);
325 ** Display the information
328 printf ("\nTable = %s\n", table);
329 printf ("+----------------------------------+----------------------------------+-------+\n");
330 printf ("| Field | Type | Length|\n");
331 printf ("+----------------------------------+----------------------------------+-------+\n");
333 /* next, print out the instances */
334 for (i=0; i < PQntuples(res); i++) {
335 printf ("| %-32.32s | ", PQgetvalue(res,i,1));
336 rtype = PQgetvalue(res,i,2);
337 rsize = atoi(PQgetvalue(res,i,3));
338 if (strcmp(rtype, "text") == 0) {
339 printf ("%-32.32s |", rtype);
340 printf ("%6s |", "var" );
342 else if (strcmp(rtype, "bpchar") == 0) {
343 printf ("%-32.32s |", "char");
344 printf ("%6i |", rsize > 0 ? rsize - 4 : 0 );
346 else if (strcmp(rtype, "varchar") == 0) {
347 printf ("%-32.32s |", rtype);
348 printf ("%6i |", rsize > 0 ? rsize - 4 : 0 );
351 /* array types start with an underscore */
353 printf ("%-32.32s |", rtype);
356 newname = malloc(strlen(rtype) + 2);
357 strcpy(newname, rtype+1);
358 strcat(newname, "[]");
359 printf ("%-32.32s |", newname);
363 printf ("%6i |", rsize);
365 printf ("%6s |", "var");
369 printf ("+----------------------------------+----------------------------------+-------+\n");
375 fprintf (stderr, "Couldn't find table %s!\n", table);
380 typedef char *(*READ_ROUTINE)(char *prompt, FILE *source);
382 /* gets_noreadline prompt source
383 gets a line of input without calling readline, the source is ignored
386 gets_noreadline(char *prompt, FILE *source)
388 fputs(prompt, stdout);
390 return(gets_fromFile(prompt,stdin));
394 * gets_readline prompt source
395 * the routine to get input from GNU readline(), the source is ignored
396 * the prompt argument is used as the prompting string
399 gets_readline(char *prompt, FILE *source)
401 return (readline(prompt));
405 * gets_fromFile prompt source
407 * the routine to read from a file, the prompt argument is ignored
408 * the source argument is a FILE *
411 gets_fromFile(char *prompt, FILE *source)
416 line = malloc(MAX_QUERY_BUFFER+1);
418 /* read up to MAX_QUERY_BUFFER characters */
419 if (fgets(line, MAX_QUERY_BUFFER, source) == NULL)
422 line[MAX_QUERY_BUFFER-1] = '\0';
424 if (len == MAX_QUERY_BUFFER)
426 fprintf(stderr, "line read exceeds maximum length. Truncating at %d\n", MAX_QUERY_BUFFER);
433 * SendQuery: send the query string to the backend
434 * return 0 if the query executed successfully
435 * returns 1 otherwise
438 SendQuery(PsqlSettings *settings, char *query)
444 if (settings->singleStep)
445 fprintf(stdout, "\n*******************************************************************************\n");
447 if (settings->echoQuery || settings->singleStep) {
448 fprintf(stderr,"QUERY: %s\n",query);
452 if (settings->singleStep) {
453 fprintf(stdout, "\n*******************************************************************************\n");
455 printf("\npress return to continue ..\n");
456 gets_fromFile("",stdin);
459 results = PQexec(settings->db, query);
460 if (results == NULL) {
461 fprintf(stderr,"%s",PQerrorMessage(settings->db));
465 switch (PQresultStatus(results)) {
466 case PGRES_TUPLES_OK:
467 if (settings->gfname)
469 PsqlSettings ps=*settings;
472 fp=setFout(&ps, settings->gfname);
473 if (!fp || fp==stdout)
485 settings->gfname=NULL;
489 PQprint(settings->queryFout,
492 fflush(settings->queryFout);
496 case PGRES_EMPTY_QUERY:
499 case PGRES_COMMAND_OK:
500 if (!settings->quiet)
501 fprintf(stdout,"%s\n", PQcmdStatus(results));
504 handleCopyOut(results, settings->quiet);
507 handleCopyIn(results, settings->quiet);
509 case PGRES_NONFATAL_ERROR:
510 case PGRES_FATAL_ERROR:
511 case PGRES_BAD_RESPONSE:
513 fprintf(stderr,"%s",PQerrorMessage(settings->db));
517 /* check for asynchronous returns */
518 notify = PQnotifies(settings->db);
520 fprintf(stderr,"ASYNC NOTIFY of '%s' from backend pid '%d' received\n",
521 notify->relname, notify->be_pid);
530 editFile(char *fname)
534 editorName = getenv("EDITOR");
536 editorName = DEFAULT_EDITOR;
537 sys=malloc(strlen(editorName)+strlen(fname)+32+1);
543 sprintf(sys, "exec '%s' '%s'", editorName, fname);
549 toggle(PsqlSettings *settings, bool *sw, char *msg)
552 if (!settings->quiet)
553 fprintf(stderr, "turned %s %s\n", on(*sw), msg);
597 Handles all the different commands that start with \
598 db_ptr is a pointer to the TgDb* structure
599 line is the current input line
600 prompt_ptr is a pointer to the prompt string,
601 a pointer is used because the prompt can be used with
602 a connection to a new database
604 0 - send currently constructed query to backend (i.e. we got a \g)
605 1 - skip processing of this line, continue building up query
606 2 - terminate processing of this query entirely
609 HandleSlashCmds(PsqlSettings *settings,
620 optarg = leftTrim(line+2);
625 case 'a': /* toggles to align fields on output */
626 toggle(settings, &settings->opt.align, "field alignment");
628 case 'C': /* define new caption */
629 if (settings->opt.caption)
630 free(settings->opt.caption);
632 settings->opt.caption=NULL;
634 if (!(settings->opt.caption=dupstr(optarg)))
640 case 'c': /* \c means connect to new database */
642 char *dbname=PQdb(settings->db);
644 fprintf(stderr,"\\c must be followed by a database name\n");
648 PGconn *olddb=settings->db;
650 printf("closing connection to database: %s\n", dbname);
651 settings->db = PQsetdb(PQhost(olddb), PQport(olddb), NULL, NULL, optarg);
652 printf("connecting to new database: %s\n", optarg);
653 if (PQstatus(settings->db) == CONNECTION_BAD) {
654 fprintf(stderr,"%s\n", PQerrorMessage(settings->db));
655 printf("reconnecting to %s\n", dbname);
656 settings->db = PQsetdb(PQhost(olddb), PQport(olddb),
658 if (PQstatus(settings->db) == CONNECTION_BAD) {
660 "could not reconnect to %s. exiting\n", dbname);
666 free(settings->prompt);
667 settings->prompt = malloc(strlen(PQdb(settings->db)) + 10);
668 sprintf(settings->prompt,"%s=> ", PQdb(settings->db));
673 case 'd': /* \d describe tables or columns in a table */
675 tableList(settings, 0);
678 if (strcmp(optarg, "*") == 0 ) {
679 tableList(settings, 0);
680 tableList(settings, 1);
683 tableDesc(settings, optarg);
692 int ql = strlen(query);
697 sprintf(tmp, "/tmp/psql.%d.%d", geteuid(), getpid());
702 if ((fd=open(tmp, O_EXCL|O_CREAT|O_WRONLY, 0600))==-1)
707 if (query[ql-1]!='\n')
709 if (write(fd, query, ql)!=ql)
720 if ((fd=open(fname, O_RDONLY))==-1)
727 if ((cc=read(fd, query, MAX_QUERY_BUFFER))==-1)
740 if (query[strlen(query)-1]==';')
747 static char *lastfile;
753 lastfile=malloc(strlen(optarg+1));
759 strcpy(lastfile, optarg);
760 } else if (!lastfile)
762 fprintf(stderr,"\\r must be followed by a file name initially\n");
767 if ((stat(lastfile, &st2) == -1) || ((fd = fopen(lastfile, "r")) == NULL))
772 if (st2.st_mtime==st.st_mtime)
774 if (!settings->quiet)
775 fprintf(stderr, "warning: %s not modified. query not executed\n", lastfile);
779 MainLoop(settings, fd);
785 char *fs=DEFAULT_FIELD_SEP;
788 if (settings->opt.fieldSep);
789 free(settings->opt.fieldSep);
790 if (!(settings->opt.fieldSep=dupstr(fs)))
795 if (!settings->quiet)
796 fprintf(stderr, "field separater changed to '%s'\n", settings->opt.fieldSep);
799 case 'g': /* \g means send query */
800 settings->gfname = optarg;
810 printf("type \\h <cmd> where <cmd> is one of the following:\n");
812 while (QL_HELP[i].cmd != NULL)
814 printf("\t%s\n", QL_HELP[i].cmd);
817 printf("type \\h * for a complete description of all commands\n");
824 while (QL_HELP[numCmds++].cmd != NULL);
826 numCmds = numCmds - 1;
828 if (strcmp(cmd, "*") == 0 ) {
832 for (i=0; i<numCmds;i++) {
833 if (strcmp(QL_HELP[i].cmd, cmd) == 0 || all_help) {
834 printf("Command: %s\n",QL_HELP[i].cmd);
835 printf("Description: %s\n", QL_HELP[i].help);
837 printf("%s\n", QL_HELP[i].syntax);
846 if (i == numCmds && ! all_help)
847 printf("command not found, try \\h with no arguments to see available help\n");
851 case 'i': /* \i is include file */
856 fprintf(stderr,"\\i must be followed by a file name\n");
860 if ((fd = fopen(optarg, "r")) == NULL)
862 fprintf(stderr,"file named %s could not be opened\n",optarg);
865 MainLoop(settings, fd);
869 case 'l': /* \l is list database */
870 listAllDbs(settings);
873 if (toggle(settings, &settings->opt.html3, "HTML3.0 tablular output"))
874 settings->opt.standard = 0;
877 setFout(settings, optarg);
882 fputs(query, stdout);
886 case 'q': /* \q is quit */
889 case 'r': /* reset(clear) the buffer */
891 if (!settings->quiet)
892 fprintf(stderr, "buffer reset(cleared)\n");
894 case 's': /* \s is save history to a file */
897 if (write_history(optarg) != 0)
898 fprintf(stderr,"cannot write history to %s\n",optarg);
900 case 'm': /* monitor like type-setting */
901 if (toggle(settings, &settings->opt.standard, "standard SQL separaters and padding"))
903 settings->opt.html3 = settings->opt.expanded = 0;
904 settings->opt.align = settings->opt.header = 1;
905 free(settings->opt.fieldSep);
906 settings->opt.fieldSep=dupstr("|");
907 if (!settings->quiet)
908 fprintf(stderr, "field separater changed to '%s'\n", settings->opt.fieldSep);
911 free(settings->opt.fieldSep);
912 settings->opt.fieldSep=dupstr(DEFAULT_FIELD_SEP);
913 if (!settings->quiet)
914 fprintf(stderr, "field separater changed to '%s'\n", settings->opt.fieldSep);
917 case 't': /* toggle headers */
918 toggle(settings, &settings->opt.header, "output headings and row count");
920 case 'T': /* define html <table ...> option */
921 if (settings->opt.tableOpt)
922 free(settings->opt.tableOpt);
924 settings->opt.tableOpt=NULL;
926 if (!(settings->opt.tableOpt=dupstr(optarg)))
933 toggle(settings, &settings->opt.expanded, "expanded table representation");
939 shellName = getenv("SHELL");
940 if (shellName == NULL)
941 shellName = DEFAULT_SHELL;
942 sys = malloc(strlen(shellName)+16);
948 sprintf(sys,"exec %s", shellName);
956 case '?': /* \? is help */
957 slashUsage(settings);
964 MainLoop: main processing loop for reading lines of input
965 and sending them to the backend
967 this loop is re-entrant. May be called by \i command
968 which reads input from a file
970 *db_ptr must be initialized and set
974 MainLoop(PsqlSettings *settings, FILE *source)
976 char *line; /* line of input */
977 int len; /* length of the line */
978 char query[MAX_QUERY_BUFFER]; /* multi-line query storage */
980 int slashCmdStatus = 0;
981 /* slashCmdStatus can be:
982 0 - send currently constructed query to backend (i.e. we got a \g)
983 1 - skip processing of this line, continue building up query
984 2 - terminate processing of this query entirely
990 READ_ROUTINE GetNextLine;
992 /* We are connected to the backend (last time we looked) */
994 /* We've reached the end of our command input. */
996 interactive = ((source == stdin) && !settings->notty);
999 if (settings->prompt)
1000 free(settings->prompt);
1001 settings->prompt = malloc(strlen(PQdb(settings->db)) + strlen(PROMPT) + 1);
1002 if (settings->quiet)
1003 settings->prompt[0] = '\0';
1005 sprintf(settings->prompt,"%s%s", PQdb(settings->db), PROMPT);
1006 if (settings->useReadline) {
1008 GetNextLine = gets_readline;
1010 GetNextLine = gets_noreadline;
1014 GetNextLine = gets_fromFile;
1018 /* main loop for getting queries and executing them */
1019 while (connected && !eof) {
1020 line = GetNextLine(settings->prompt, source);
1021 if (line == NULL) { /* No more input. Time to quit */
1022 printf("EOF\n"); /* Goes on prompt line */
1026 line = rightTrim(line); /* remove whitespaces on the right, incl. \n's */
1028 if (line[0] == '\0') {
1033 /* filter out comment lines that begin with --,
1034 this could be incorrect if -- is part of a quoted string.
1035 But we won't go through the trouble of detecting that. If you have
1036 -- in your quoted string, be careful and don't start a line with it */
1037 if (line[0] == '-' && line[1] == '-') {
1038 if (settings->singleStep) /* in single step mode, show comments */
1039 fprintf(stdout,"%s\n",line);
1043 if (line[0] != '\\' && querySent)
1051 if (interactive && settings->useReadline)
1052 add_history(line); /* save non-empty lines in history */
1054 /* do the query immediately if we are doing single line queries
1055 or if the last character is a semicolon */
1056 sendQuery = settings->singleLineMode || (line[len-1] == ';') ;
1058 /* normally, \ commands have to be start the line,
1059 but for backwards compatibility with monitor,
1060 check for \g at the end of line */
1061 if (len > 2 && !sendQuery)
1063 if (line[len-1]=='g' && line[len-2]=='\\')
1070 /* slash commands have to be on their own line */
1071 if (line[0] == '\\') {
1072 slashCmdStatus = HandleSlashCmds(settings,
1075 if (slashCmdStatus == 1) {
1079 if (slashCmdStatus == 2) {
1083 if (slashCmdStatus == 0)
1087 if (strlen(query) + len > MAX_QUERY_BUFFER)
1089 fprintf(stderr,"query buffer max length of %d exceeded\n",MAX_QUERY_BUFFER);
1090 fprintf(stderr,"query line ignored\n");
1093 if (query[0]!='\0') {
1100 if (sendQuery && query[0] != '\0')
1102 /* echo the line read from the file,
1103 unless we are in single_step mode, because single_step mode
1105 if (!interactive && !settings->singleStep && !settings->quiet)
1106 fprintf(stderr,"%s\n", query);
1108 exitStatus = SendQuery(settings, query);
1110 if (PQstatus(settings->db) == CONNECTION_BAD) {
1112 fprintf(stderr, "We have lost the connection to the backend, so "
1113 "further processing is impossible. Terminating.\n");
1116 free(line); /* free storage malloc'd by GetNextLine */
1123 main(int argc, char **argv)
1125 extern char *optarg;
1128 char *dbname = NULL;
1131 char *qfilename = NULL;
1132 char errbuf[ERROR_MSG_LENGTH];
1134 PsqlSettings settings;
1136 char *singleQuery = NULL;
1138 bool listDatabases = 0 ;
1140 bool singleSlashCmd = 0;
1143 memset(&settings, 0, sizeof settings);
1144 settings.opt.align = 1;
1145 settings.opt.header = 1;
1146 settings.queryFout = stdout;
1147 settings.opt.fieldSep=dupstr(DEFAULT_FIELD_SEP);
1148 settings.opt.pager = 1;
1149 if (!isatty(0) || !isatty(1))
1150 settings.quiet = settings.notty = 1;
1153 settings.useReadline = 1;
1156 while ((c = getopt(argc, argv, "Aa:c:d:ef:F:lh:Hnso:p:qStT:x")) != EOF) {
1159 settings.opt.align = 0;
1162 fe_setauthsvc(optarg, errbuf);
1165 singleQuery = optarg;
1166 if ( singleQuery[0] == '\\' ) {
1174 settings.echoQuery = 1;
1180 settings.opt.fieldSep=optarg;
1189 settings.opt.html3 = 1;
1192 settings.useReadline = 0;
1195 setFout(&settings, optarg);
1204 settings.singleStep = 1;
1207 settings.singleLineMode = 1;
1210 settings.opt.header = 0;
1213 settings.opt.tableOpt = optarg;
1216 settings.opt.expanded = 0;
1223 /* if we still have an argument, use it as the database name */
1224 if (argc - optind == 1)
1225 dbname = argv[optind];
1228 dbname = "template1";
1230 settings.db = PQsetdb(host, port, NULL, NULL, dbname);
1231 dbname = PQdb(settings.db);
1233 if (PQstatus(settings.db) == CONNECTION_BAD) {
1234 fprintf(stderr,"Connection to database '%s' failed.\n", dbname);
1235 fprintf(stderr,"%s",PQerrorMessage(settings.db));
1238 if (listDatabases) {
1239 exit(listAllDbs(&settings));
1242 if (!settings.quiet && !singleQuery && !qfilename) {
1243 printf("Welcome to the POSTGRES95 interactive sql monitor:\n");
1244 printf(" Please read the file COPYRIGHT for copyright terms of POSTGRES95\n\n");
1245 printf(" type \\? for help on slash commands\n");
1246 printf(" type \\q to quit\n");
1247 printf(" type \\g or terminate with semicolon to execute query\n");
1248 printf(" You are currently connected to the database: %s\n\n", dbname);
1251 if (qfilename || singleSlashCmd) {
1252 /* read in a file full of queries instead of reading in queries
1256 if ( singleSlashCmd ) {
1257 /* Not really a query, but "Do what I mean, not what I say." */
1261 line = malloc(strlen(qfilename) + 5);
1262 sprintf(line,"\\i %s", qfilename);
1264 HandleSlashCmds(&settings, line, "");
1268 exitStatus = SendQuery(&settings, singleQuery);
1271 exitStatus = MainLoop(&settings, stdin);
1274 PQfinish(settings.db);
1279 #define COPYBUFSIZ 8192
1282 handleCopyOut(PGresult *res, bool quiet)
1284 bool copydone = false;
1285 char copybuf[COPYBUFSIZ];
1289 fprintf(stdout, "Copy command returns...\n");
1292 ret = PQgetline(res->conn, copybuf, COPYBUFSIZ);
1294 if (copybuf[0] == '.' && copybuf[1] =='\0') {
1295 copydone = true; /* don't print this... */
1297 fputs(copybuf, stdout);
1303 fputc('\n', stdout);
1311 PQendcopy(res->conn);
1316 handleCopyIn(PGresult *res, bool quiet)
1318 bool copydone = false;
1321 char copybuf[COPYBUFSIZ];
1327 fputs("Enter info followed by a newline\n", stdout);
1328 fputs("End with a dot on a line by itself.\n", stdout);
1332 * eat extra newline still in input buffer
1336 if ((c = getc(stdin)) != '\n' && c != EOF) {
1337 (void) ungetc(c, stdin);
1340 while (!copydone) { /* for each input line ... */
1342 fputs(">> ", stdout);
1347 while (!linedone) { /* for each buffer ... */
1349 buflen = COPYBUFSIZ;
1350 for (; buflen > 1 &&
1351 !(linedone = (c = getc(stdin)) == '\n' || c == EOF);
1356 /* reading from stdin, but from a file */
1357 PQputline(res->conn, ".");
1362 PQputline(res->conn, copybuf);
1364 if (!strcmp(copybuf, ".")) {
1370 PQputline(res->conn, "\n");
1372 PQendcopy(res->conn);
1375 /* try to open fname and return a FILE *,
1376 if it fails, use stdout, instead */
1379 setFout(PsqlSettings *ps, char *fname)
1381 if (ps->queryFout && ps->queryFout != stdout)
1384 pclose(ps->queryFout);
1386 fclose(ps->queryFout);
1389 ps->queryFout = stdout;
1394 signal(SIGPIPE, SIG_IGN);
1395 ps->queryFout = popen(fname+1, "w");
1400 ps->queryFout = fopen(fname, "w");
1403 if (!ps->queryFout) {
1405 ps->queryFout = stdout;
1408 return ps->queryFout;