]> granicus.if.org Git - postgresql/blob - src/bin/psql/common.c
Add get_home_path() to use USERPROFILE on Win32 and HOME on Unix.
[postgresql] / src / bin / psql / common.c
1 /*
2  * psql - the PostgreSQL interactive terminal
3  *
4  * Copyright (c) 2000-2003, PostgreSQL Global Development Group
5  *
6  * $PostgreSQL: pgsql/src/bin/psql/common.c,v 1.88 2004/08/18 02:59:11 momjian Exp $
7  */
8 #include "postgres_fe.h"
9 #include "common.h"
10
11 #include <ctype.h>
12 #ifndef HAVE_STRDUP
13 #include <strdup.h>
14 #endif
15 #include <signal.h>
16 #ifndef WIN32
17 #include <sys/time.h>
18 #include <unistd.h>                             /* for write() */
19 #include <setjmp.h>
20 #else
21 #include <io.h>                                 /* for _write() */
22 #include <win32.h>
23 #include <sys/timeb.h>                  /* for _ftime() */
24 #endif
25
26 #include "libpq-fe.h"
27 #include "pqsignal.h"
28
29 #include "settings.h"
30 #include "variables.h"
31 #include "command.h"
32 #include "copy.h"
33 #include "prompt.h"
34 #include "print.h"
35 #include "mainloop.h"
36 #include "mb/pg_wchar.h"
37
38
39 /* Workarounds for Windows */
40 /* Probably to be moved up the source tree in the future, perhaps to be replaced by
41  * more specific checks like configure-style HAVE_GETTIMEOFDAY macros.
42  */
43 #ifndef WIN32
44
45 typedef struct timeval TimevalStruct;
46
47 #define GETTIMEOFDAY(T) gettimeofday(T, NULL)
48 #define DIFF_MSEC(T, U) \
49         ((((int) ((T)->tv_sec - (U)->tv_sec)) * 1000000.0 + \
50           ((int) ((T)->tv_usec - (U)->tv_usec))) / 1000.0)
51
52 #else
53
54 typedef struct _timeb TimevalStruct;
55
56 #define GETTIMEOFDAY(T) _ftime(T)
57 #define DIFF_MSEC(T, U) \
58         (((T)->time - (U)->time) * 1000.0 + \
59          ((T)->millitm - (U)->millitm))
60
61 #endif
62
63 extern bool prompt_state;
64
65
66 static bool is_transact_command(const char *query);
67
68
69 /*
70  * "Safe" wrapper around strdup()
71  */
72 char *
73 pg_strdup(const char *string)
74 {
75         char       *tmp;
76
77         if (!string)
78         {
79                 fprintf(stderr, gettext("%s: xstrdup: cannot duplicate null pointer (internal error)\n"),
80                                 pset.progname);
81                 exit(EXIT_FAILURE);
82         }
83         tmp = strdup(string);
84         if (!tmp)
85         {
86                 psql_error("out of memory\n");
87                 exit(EXIT_FAILURE);
88         }
89         return tmp;
90 }
91
92 void *
93 pg_malloc(size_t size)
94 {
95         void       *tmp;
96
97         tmp = malloc(size);
98         if (!tmp)
99         {
100                 psql_error("out of memory\n");
101                 exit(EXIT_FAILURE);
102         }
103         return tmp;
104 }
105
106 void *
107 pg_malloc_zero(size_t size)
108 {
109         void       *tmp;
110
111         tmp = pg_malloc(size);
112         memset(tmp, 0, size);
113         return tmp;
114 }
115
116 void *
117 pg_calloc(size_t nmemb, size_t size)
118 {
119         void       *tmp;
120
121         tmp = calloc(nmemb, size);
122         if (!tmp)
123         {
124                 psql_error("out of memory");
125                 exit(EXIT_FAILURE);
126         }
127         return tmp;
128 }
129
130 /*
131  * setQFout
132  * -- handler for -o command line option and \o command
133  *
134  * Tries to open file fname (or pipe if fname starts with '|')
135  * and stores the file handle in pset)
136  * Upon failure, sets stdout and returns false.
137  */
138 bool
139 setQFout(const char *fname)
140 {
141         bool            status = true;
142
143         /* Close old file/pipe */
144         if (pset.queryFout && pset.queryFout != stdout && pset.queryFout != stderr)
145         {
146                 if (pset.queryFoutPipe)
147                         pclose(pset.queryFout);
148                 else
149                         fclose(pset.queryFout);
150         }
151
152         /* If no filename, set stdout */
153         if (!fname || fname[0] == '\0')
154         {
155                 pset.queryFout = stdout;
156                 pset.queryFoutPipe = false;
157         }
158         else if (*fname == '|')
159         {
160                 pset.queryFout = popen(fname + 1, "w");
161                 pset.queryFoutPipe = true;
162         }
163         else
164         {
165                 pset.queryFout = fopen(fname, "w");
166                 pset.queryFoutPipe = false;
167         }
168
169         if (!(pset.queryFout))
170         {
171                 psql_error("%s: %s\n", fname, strerror(errno));
172                 pset.queryFout = stdout;
173                 pset.queryFoutPipe = false;
174                 status = false;
175         }
176
177         /* Direct signals */
178 #ifndef WIN32
179         pqsignal(SIGPIPE, pset.queryFoutPipe ? SIG_IGN : SIG_DFL);
180 #endif
181
182         return status;
183 }
184
185
186
187 /*
188  * Error reporting for scripts. Errors should look like
189  *       psql:filename:lineno: message
190  *
191  */
192 void
193 psql_error(const char *fmt,...)
194 {
195         va_list         ap;
196
197         fflush(stdout);
198         if (pset.queryFout != stdout)
199                 fflush(pset.queryFout);
200
201         if (pset.inputfile)
202                 fprintf(stderr, "%s:%s:%u: ", pset.progname, pset.inputfile, pset.lineno);
203         va_start(ap, fmt);
204         vfprintf(stderr, gettext(fmt), ap);
205         va_end(ap);
206 }
207
208
209
210 /*
211  * for backend Notice messages (INFO, WARNING, etc)
212  */
213 void
214 NoticeProcessor(void *arg, const char *message)
215 {
216         (void) arg;                                     /* not used */
217         psql_error("%s", message);
218 }
219
220
221
222 /*
223  * Code to support query cancellation
224  *
225  * Before we start a query, we enable a SIGINT signal catcher that sends a
226  * cancel request to the backend. Note that sending the cancel directly from
227  * the signal handler is safe because PQrequestCancel() is written to make it
228  * so. We use write() to print to stdout because it's better to use simple
229  * facilities in a signal handler.
230  */
231 static PGconn *volatile cancelConn = NULL;
232
233 volatile bool cancel_pressed = false;
234
235
236 #ifndef WIN32
237
238 #define write_stderr(String) write(fileno(stderr), String, strlen(String))
239
240 void
241 handle_sigint(SIGNAL_ARGS)
242 {
243         int                     save_errno = errno;
244
245         /* Don't muck around if prompting for a password. */
246         if (prompt_state)
247                 return;
248
249         if (cancelConn == NULL)
250                 siglongjmp(main_loop_jmp, 1);
251
252         cancel_pressed = true;
253
254         if (PQrequestCancel(cancelConn))
255                 write_stderr("Cancel request sent\n");
256         else
257         {
258                 write_stderr("Could not send cancel request: ");
259                 write_stderr(PQerrorMessage(cancelConn));
260         }
261         errno = save_errno;                     /* just in case the write changed it */
262 }
263 #endif   /* not WIN32 */
264
265
266
267 /* ConnectionUp
268  *
269  * Returns whether our backend connection is still there.
270  */
271 static bool
272 ConnectionUp()
273 {
274         return PQstatus(pset.db) != CONNECTION_BAD;
275 }
276
277
278
279 /* CheckConnection
280  *
281  * Verify that we still have a good connection to the backend, and if not,
282  * see if it can be restored.
283  *
284  * Returns true if either the connection was still there, or it could be
285  * restored successfully; false otherwise.      If, however, there was no
286  * connection and the session is non-interactive, this will exit the program
287  * with a code of EXIT_BADCONN.
288  */
289 static bool
290 CheckConnection(void)
291 {
292         bool            OK;
293
294         OK = ConnectionUp();
295         if (!OK)
296         {
297                 if (!pset.cur_cmd_interactive)
298                 {
299                         psql_error("connection to server was lost\n");
300                         exit(EXIT_BADCONN);
301                 }
302
303                 fputs(gettext("The connection to the server was lost. Attempting reset: "), stderr);
304                 PQreset(pset.db);
305                 OK = ConnectionUp();
306                 if (!OK)
307                 {
308                         fputs(gettext("Failed.\n"), stderr);
309                         PQfinish(pset.db);
310                         pset.db = NULL;
311                         ResetCancelConn();
312                         UnsyncVariables();
313                 }
314                 else
315                         fputs(gettext("Succeeded.\n"), stderr);
316         }
317
318         return OK;
319 }
320
321
322
323 /*
324  * SetCancelConn
325  *
326  * Set cancelConn to point to the current database connection.
327  */
328 static void
329 SetCancelConn(void)
330 {
331         cancelConn = pset.db;
332 }
333
334
335 /*
336  * ResetCancelConn
337  *
338  * Set cancelConn to NULL.      I don't know what this means exactly, but it saves
339  * having to export the variable.
340  */
341 void
342 ResetCancelConn(void)
343 {
344         cancelConn = NULL;
345 }
346
347
348 /*
349  * on errors, print syntax error position if available.
350  *
351  * the query is expected to be in the client encoding.
352  */
353 static void
354 ReportSyntaxErrorPosition(const PGresult *result, const char *query)
355 {
356 #define DISPLAY_SIZE    60              /* screen width limit, in screen cols */
357 #define MIN_RIGHT_CUT   10              /* try to keep this far away from EOL */
358
359         int                     loc = 0;
360         const char *sp;
361         int clen, slen, i, *qidx, *scridx, qoffset, scroffset, ibeg, iend,
362                 loc_line;
363         char *wquery;
364         bool beg_trunc, end_trunc;
365         PQExpBufferData msg;
366
367         if (pset.verbosity == PQERRORS_TERSE)
368                 return;
369
370         sp = PQresultErrorField(result, PG_DIAG_STATEMENT_POSITION);
371         if (sp == NULL)
372         {
373                 sp = PQresultErrorField(result, PG_DIAG_INTERNAL_POSITION);
374                 if (sp == NULL)
375                         return;                         /* no syntax error */
376                 query = PQresultErrorField(result, PG_DIAG_INTERNAL_QUERY);
377         }
378         if (query == NULL)
379                 return;                                 /* nothing to reference location to */
380
381         if (sscanf(sp, "%d", &loc) != 1)
382         {
383                 psql_error("INTERNAL ERROR: unexpected statement position \"%s\"\n",
384                                    sp);
385                 return;
386         }
387
388         /* Make a writable copy of the query, and a buffer for messages. */
389         wquery = pg_strdup(query);
390
391         initPQExpBuffer(&msg);
392
393         /*
394          * The returned cursor position is measured in logical characters.
395          * Each character might occupy multiple physical bytes in the string,
396          * and in some Far Eastern character sets it might take more than one
397          * screen column as well.  We compute the starting byte offset and
398          * starting screen column of each logical character, and store these
399          * in qidx[] and scridx[] respectively.
400          */
401
402         /* we need a safe allocation size... */
403         slen = strlen(query) + 1;
404
405         qidx = (int *) pg_malloc(slen * sizeof(int));
406         scridx = (int *) pg_malloc(slen * sizeof(int));
407
408         qoffset = 0;
409         scroffset = 0;
410         for (i = 0; query[qoffset] != '\0'; i++)
411         {
412                 qidx[i] = qoffset;
413                 scridx[i] = scroffset;
414                 scroffset += PQdsplen(&query[qoffset], pset.encoding);
415                 qoffset += PQmblen(&query[qoffset], pset.encoding);
416         }
417         qidx[i] = qoffset;
418         scridx[i] = scroffset;
419         clen = i;
420         psql_assert(clen < slen);
421
422         /* convert loc to zero-based offset in qidx/scridx arrays */
423         loc--; 
424
425         /* do we have something to show? */
426         if (loc >= 0 && loc <= clen)
427         {
428                  /* input line number of our syntax error. */
429                 loc_line = 1;
430                 /* first included char of extract. */
431                 ibeg = 0; 
432                 /* last-plus-1 included char of extract. */
433                 iend = clen; 
434
435                 /*
436                  * Replace tabs with spaces in the writable copy.  (Later we might
437                  * want to think about coping with their variable screen width,
438                  * but not today.)
439                  *
440                  * Extract line number and begin and end indexes of line containing
441                  * error location.  There will not be any newlines or carriage
442                  * returns in the selected extract.
443                  */
444                 for (i=0; i<clen; i++)
445                 {
446                         /* character length must be 1 or it's not ASCII */
447                         if ((qidx[i+1]-qidx[i]) == 1)
448                         {
449                                 if (wquery[qidx[i]] == '\t') 
450                                         wquery[qidx[i]] = ' ';
451                                 else if (wquery[qidx[i]] == '\r' || wquery[qidx[i]] == '\n')
452                                 {
453                                         if (i < loc)
454                                         {
455                                                 /*
456                                                  * count lines before loc.  Each \r or \n counts
457                                                  * as a line except when \r \n appear together.
458                                                  */
459                                                 if (wquery[qidx[i]] == '\r' ||
460                                                         i == 0 ||
461                                                         (qidx[i]-qidx[i-1]) != 1 ||
462                                                         wquery[qidx[i-1]] != '\r')
463                                                         loc_line++;
464                                                 /* extract beginning = last line start before loc. */
465                                                 ibeg = i+1;
466                                         }
467                                         else
468                                         {
469                                                 /* set extract end. */
470                                                 iend = i;
471                                                 /* done scanning. */
472                                                 break;
473                                         }
474                                 }
475                         }
476                 }
477
478                 /* If the line extracted is too long, we truncate it. */
479                 beg_trunc = false;
480                 end_trunc = false;
481                 if (scridx[iend]-scridx[ibeg] > DISPLAY_SIZE)
482                 {
483                         /*
484                          * We first truncate right if it is enough.  This code might
485                          * be off a space or so on enforcing MIN_RIGHT_CUT if there's
486                          * a wide character right there, but that should be okay.
487                          */
488                         if (scridx[ibeg]+DISPLAY_SIZE >= scridx[loc]+MIN_RIGHT_CUT)
489                         {
490                                 while (scridx[iend]-scridx[ibeg] > DISPLAY_SIZE)
491                                         iend--;
492                                 end_trunc = true;
493                         }
494                         else
495                         {
496                                 /* Truncate right if not too close to loc. */
497                                 while (scridx[loc]+MIN_RIGHT_CUT < scridx[iend])
498                                 {
499                                         iend--;
500                                         end_trunc = true;
501                                 }
502
503                                 /* Truncate left if still too long. */
504                                 while (scridx[iend]-scridx[ibeg] > DISPLAY_SIZE)
505                                 {
506                                         ibeg++;
507                                         beg_trunc = true;
508                                 }
509                         }
510                 }
511
512                 /* the extract MUST contain the target position! */
513                 psql_assert(ibeg<=loc && loc<=iend);
514
515                 /* truncate working copy at desired endpoint */
516                 wquery[qidx[iend]] = '\0';
517
518                 /* Begin building the finished message. */
519                 printfPQExpBuffer(&msg, gettext("LINE %d: "), loc_line);
520                 if (beg_trunc)
521                         appendPQExpBufferStr(&msg, "...");
522
523                 /*
524                  * While we have the prefix in the msg buffer, compute its screen
525                  * width.
526                  */
527                 scroffset = 0;
528                 for (i = 0; i < msg.len; i += PQmblen(&msg.data[i], pset.encoding))
529                 {
530                         scroffset += PQdsplen(&msg.data[i], pset.encoding);
531                 }
532
533                 /* Finish and emit the message. */
534                 appendPQExpBufferStr(&msg, &wquery[qidx[ibeg]]);
535                 if (end_trunc)
536                         appendPQExpBufferStr(&msg, "...");
537
538                 psql_error("%s\n", msg.data);
539
540                 /* Now emit the cursor marker line. */
541                 scroffset += scridx[loc] - scridx[ibeg];
542                 resetPQExpBuffer(&msg);
543                 for (i = 0; i < scroffset; i++)
544                         appendPQExpBufferChar(&msg, ' ');
545                 appendPQExpBufferChar(&msg, '^');
546
547                 psql_error("%s\n", msg.data);
548         }
549
550         /* Clean up. */
551         termPQExpBuffer(&msg);
552
553         free(wquery);
554         free(qidx);
555         free(scridx);
556 }
557
558
559 /*
560  * AcceptResult
561  *
562  * Checks whether a result is valid, giving an error message if necessary;
563  * resets cancelConn as needed, and ensures that the connection to the backend
564  * is still up.
565  *
566  * Returns true for valid result, false for error state.
567  */
568 static bool
569 AcceptResult(const PGresult *result, const char *query)
570 {
571         bool            OK = true;
572
573         ResetCancelConn();
574
575         if (!result)
576                 OK = false;
577         else
578                 switch (PQresultStatus(result))
579                 {
580                         case PGRES_COMMAND_OK:
581                         case PGRES_TUPLES_OK:
582                         case PGRES_EMPTY_QUERY:
583                         case PGRES_COPY_IN:
584                                 /* Fine, do nothing */
585                                 break;
586
587                         case PGRES_COPY_OUT:
588                                 /* keep cancel connection for copy out state */
589                                 SetCancelConn();
590                                 break;
591
592                         default:
593                                 OK = false;
594                                 break;
595                 }
596
597         if (!OK)
598         {
599                 psql_error("%s", PQerrorMessage(pset.db));
600                 ReportSyntaxErrorPosition(result, query);
601                 CheckConnection();
602         }
603
604         return OK;
605 }
606
607
608
609 /*
610  * PSQLexec
611  *
612  * This is the way to send "backdoor" queries (those not directly entered
613  * by the user). It is subject to -E but not -e.
614  *
615  * In autocommit-off mode, a new transaction block is started if start_xact
616  * is true; nothing special is done when start_xact is false.  Typically,
617  * start_xact = false is used for SELECTs and explicit BEGIN/COMMIT commands.
618  *
619  * Note: we don't bother to check PQclientEncoding; it is assumed that no
620  * caller uses this path to issue "SET CLIENT_ENCODING".
621  */
622 PGresult *
623 PSQLexec(const char *query, bool start_xact)
624 {
625         PGresult   *res;
626         int                     echo_hidden;
627
628         if (!pset.db)
629         {
630                 psql_error("You are currently not connected to a database.\n");
631                 return NULL;
632         }
633
634         echo_hidden = SwitchVariable(pset.vars, "ECHO_HIDDEN", "noexec", NULL);
635         if (echo_hidden != VAR_NOTSET)
636         {
637                 printf("********* QUERY **********\n"
638                            "%s\n"
639                            "**************************\n\n", query);
640                 fflush(stdout);
641
642                 if (echo_hidden == 1)   /* noexec? */
643                         return NULL;
644         }
645
646         SetCancelConn();
647
648         if (start_xact && PQtransactionStatus(pset.db) == PQTRANS_IDLE &&
649                 !GetVariableBool(pset.vars, "AUTOCOMMIT"))
650         {
651                 res = PQexec(pset.db, "BEGIN");
652                 if (PQresultStatus(res) != PGRES_COMMAND_OK)
653                 {
654                         psql_error("%s", PQerrorMessage(pset.db));
655                         PQclear(res);
656                         ResetCancelConn();
657                         return NULL;
658                 }
659                 PQclear(res);
660         }
661
662         res = PQexec(pset.db, query);
663
664         if (!AcceptResult(res, query) && res)
665         {
666                 PQclear(res);
667                 res = NULL;
668         }
669
670         return res;
671 }
672
673
674
675 /*
676  * PrintNotifications: check for asynchronous notifications, and print them out
677  */
678 static void
679 PrintNotifications(void)
680 {
681         PGnotify   *notify;
682
683         while ((notify = PQnotifies(pset.db)))
684         {
685                 fprintf(pset.queryFout, gettext("Asynchronous notification \"%s\" received from server process with PID %d.\n"),
686                                 notify->relname, notify->be_pid);
687                 fflush(pset.queryFout);
688                 PQfreemem(notify);
689         }
690 }
691
692
693 /*
694  * PrintQueryTuples: assuming query result is OK, print its tuples
695  *
696  * Returns true if successful, false otherwise.
697  */
698 static bool
699 PrintQueryTuples(const PGresult *results)
700 {
701         /* write output to \g argument, if any */
702         if (pset.gfname)
703         {
704                 FILE       *queryFout_copy = pset.queryFout;
705                 bool            queryFoutPipe_copy = pset.queryFoutPipe;
706
707                 pset.queryFout = stdout;        /* so it doesn't get closed */
708
709                 /* open file/pipe */
710                 if (!setQFout(pset.gfname))
711                 {
712                         pset.queryFout = queryFout_copy;
713                         pset.queryFoutPipe = queryFoutPipe_copy;
714                         return false;
715                 }
716
717                 printQuery(results, &pset.popt, pset.queryFout);
718
719                 /* close file/pipe, restore old setting */
720                 setQFout(NULL);
721
722                 pset.queryFout = queryFout_copy;
723                 pset.queryFoutPipe = queryFoutPipe_copy;
724
725                 free(pset.gfname);
726                 pset.gfname = NULL;
727         }
728         else
729                 printQuery(results, &pset.popt, pset.queryFout);
730
731         return true;
732 }
733
734
735 /*
736  * ProcessCopyResult: if command was a COPY FROM STDIN/TO STDOUT, handle it
737  *
738  * Note: Utility function for use by SendQuery() only.
739  *
740  * Returns true if the query executed successfully, false otherwise.
741  */
742 static bool
743 ProcessCopyResult(PGresult *results)
744 {
745         bool            success = false;
746
747         if (!results)
748                 return false;
749
750         switch (PQresultStatus(results))
751         {
752                 case PGRES_TUPLES_OK:
753                 case PGRES_COMMAND_OK:
754                 case PGRES_EMPTY_QUERY:
755                         /* nothing to do here */
756                         success = true;
757                         break;
758
759                 case PGRES_COPY_OUT:
760                         success = handleCopyOut(pset.db, pset.queryFout);
761                         break;
762
763                 case PGRES_COPY_IN:
764                         success = handleCopyIn(pset.db, pset.cur_cmd_source);
765                         break;
766
767                 default:
768                         break;
769         }
770
771         /* may need this to recover from conn loss during COPY */
772         if (!CheckConnection())
773                 return false;
774
775         return success;
776 }
777
778
779 /*
780  * PrintQueryResults: print out query results as required
781  *
782  * Note: Utility function for use by SendQuery() only.
783  *
784  * Returns true if the query executed successfully, false otherwise.
785  */
786 static bool
787 PrintQueryResults(PGresult *results)
788 {
789         bool            success = false;
790
791         if (!results)
792                 return false;
793
794         switch (PQresultStatus(results))
795         {
796                 case PGRES_TUPLES_OK:
797                         success = PrintQueryTuples(results);
798                         break;
799
800                 case PGRES_COMMAND_OK:
801                         {
802                                 char            buf[10];
803
804                                 success = true;
805                                 snprintf(buf, sizeof(buf),
806                                                  "%u", (unsigned int) PQoidValue(results));
807                                 if (!QUIET())
808                                 {
809                                         if (pset.popt.topt.format == PRINT_HTML)
810                                         {
811                                                 fputs("<p>", pset.queryFout);
812                                                 html_escaped_print(PQcmdStatus(results),
813                                                                                    pset.queryFout);
814                                                 fputs("</p>\n", pset.queryFout);
815                                         }
816                                         else
817                                                 fprintf(pset.queryFout, "%s\n", PQcmdStatus(results));
818                                 }
819                                 SetVariable(pset.vars, "LASTOID", buf);
820                                 break;
821                         }
822
823                 case PGRES_EMPTY_QUERY:
824                         success = true;
825                         break;
826
827                 case PGRES_COPY_OUT:
828                 case PGRES_COPY_IN:
829                         /* nothing to do here */
830                         success = true;
831                         break;
832
833                 default:
834                         break;
835         }
836
837         fflush(pset.queryFout);
838
839         return success;
840 }
841
842
843 /*
844  * SendQuery: send the query string to the backend
845  * (and print out results)
846  *
847  * Note: This is the "front door" way to send a query. That is, use it to
848  * send queries actually entered by the user. These queries will be subject to
849  * single step mode.
850  * To send "back door" queries (generated by slash commands, etc.) in a
851  * controlled way, use PSQLexec().
852  *
853  * Returns true if the query executed successfully, false otherwise.
854  */
855 bool
856 SendQuery(const char *query)
857 {
858         PGresult   *results;
859         TimevalStruct before,
860                                 after;
861         bool            OK;
862
863         if (!pset.db)
864         {
865                 psql_error("You are currently not connected to a database.\n");
866                 return false;
867         }
868
869         if (GetVariableBool(pset.vars, "SINGLESTEP"))
870         {
871                 char            buf[3];
872
873                 printf(gettext("***(Single step mode: verify command)*******************************************\n"
874                                            "%s\n"
875                                            "***(press return to proceed or enter x and return to cancel)********************\n"),
876                            query);
877                 fflush(stdout);
878                 if (fgets(buf, sizeof(buf), stdin) != NULL)
879                         if (buf[0] == 'x')
880                                 return false;
881         }
882         else if (VariableEquals(pset.vars, "ECHO", "queries"))
883         {
884                 puts(query);
885                 fflush(stdout);
886         }
887
888         SetCancelConn();
889
890         if (PQtransactionStatus(pset.db) == PQTRANS_IDLE &&
891                 !GetVariableBool(pset.vars, "AUTOCOMMIT") &&
892                 !is_transact_command(query))
893         {
894                 results = PQexec(pset.db, "BEGIN");
895                 if (PQresultStatus(results) != PGRES_COMMAND_OK)
896                 {
897                         psql_error("%s", PQerrorMessage(pset.db));
898                         PQclear(results);
899                         ResetCancelConn();
900                         return false;
901                 }
902                 PQclear(results);
903         }
904
905         if (pset.timing)
906                 GETTIMEOFDAY(&before);
907
908         results = PQexec(pset.db, query);
909
910         /* these operations are included in the timing result: */
911         OK = (AcceptResult(results, query) && ProcessCopyResult(results));
912
913         if (pset.timing)
914                 GETTIMEOFDAY(&after);
915
916         /* but printing results isn't: */
917         if (OK)
918                 OK = PrintQueryResults(results);
919
920         PQclear(results);
921
922         /* Possible microtiming output */
923         if (OK && pset.timing)
924                 printf(gettext("Time: %.3f ms\n"), DIFF_MSEC(&after, &before));
925
926         /* check for events that may occur during query execution */
927
928         if (pset.encoding != PQclientEncoding(pset.db) &&
929                 PQclientEncoding(pset.db) >= 0)
930         {
931                 /* track effects of SET CLIENT_ENCODING */
932                 pset.encoding = PQclientEncoding(pset.db);
933                 pset.popt.topt.encoding = pset.encoding;
934                 SetVariable(pset.vars, "ENCODING",
935                                         pg_encoding_to_char(pset.encoding));
936         }
937
938         PrintNotifications();
939
940         return OK;
941 }
942
943 /*
944  * check whether a query string begins with BEGIN/COMMIT/ROLLBACK/START XACT
945  */
946 static bool
947 is_transact_command(const char *query)
948 {
949         int                     wordlen;
950
951         /*
952          * First we must advance over any whitespace and comments.
953          */
954         while (*query)
955         {
956                 if (isspace((unsigned char) *query))
957                         query++;
958                 else if (query[0] == '-' && query[1] == '-')
959                 {
960                         query += 2;
961                         while (*query && *query != '\n')
962                                 query++;
963                 }
964                 else if (query[0] == '/' && query[1] == '*')
965                 {
966                         query += 2;
967                         while (*query)
968                         {
969                                 if (query[0] == '*' && query[1] == '/')
970                                 {
971                                         query += 2;
972                                         break;
973                                 }
974                                 else
975                                         query++;
976                         }
977                 }
978                 else
979                         break;                          /* found first token */
980         }
981
982         /*
983          * Check word length ("beginx" is not "begin").
984          */
985         wordlen = 0;
986         while (isalpha((unsigned char) query[wordlen]))
987                 wordlen++;
988
989         if (wordlen == 5 && pg_strncasecmp(query, "begin", 5) == 0)
990                 return true;
991         if (wordlen == 6 && pg_strncasecmp(query, "commit", 6) == 0)
992                 return true;
993         if (wordlen == 8 && pg_strncasecmp(query, "rollback", 8) == 0)
994                 return true;
995         if (wordlen == 5 && pg_strncasecmp(query, "abort", 5) == 0)
996                 return true;
997         if (wordlen == 3 && pg_strncasecmp(query, "end", 3) == 0)
998                 return true;
999         if (wordlen == 5 && pg_strncasecmp(query, "start", 5) == 0)
1000                 return true;
1001
1002         return false;
1003 }
1004
1005
1006 char
1007 parse_char(char **buf)
1008 {
1009         long            l;
1010
1011         l = strtol(*buf, buf, 0);
1012         --*buf;
1013         return (char) l;
1014 }
1015
1016
1017 /*
1018  * Test if the current user is a database superuser.
1019  *
1020  * Note: this will correctly detect superuserness only with a protocol-3.0
1021  * or newer backend; otherwise it will always say "false".
1022  */
1023 bool
1024 is_superuser(void)
1025 {
1026         const char *val;
1027
1028         if (!pset.db)
1029                 return false;
1030
1031         val = PQparameterStatus(pset.db, "is_superuser");
1032
1033         if (val && strcmp(val, "on") == 0)
1034                 return true;
1035
1036         return false;
1037 }
1038
1039
1040 /*
1041  * Return the session user of the current connection.
1042  *
1043  * Note: this will correctly detect the session user only with a
1044  * protocol-3.0 or newer backend; otherwise it will return the
1045  * connection user.
1046  */
1047 const char *
1048 session_username(void)
1049 {
1050         const char *val;
1051
1052         if (!pset.db)
1053                 return NULL;
1054
1055         val = PQparameterStatus(pset.db, "session_authorization");
1056         if (val)
1057                 return val;
1058         else
1059                 return PQuser(pset.db);
1060 }
1061
1062
1063 /* expand_tilde
1064  *
1065  * substitute '~' with HOME or '~username' with username's home dir
1066  *
1067  */
1068 char *
1069 expand_tilde(char **filename)
1070 {
1071         if (!filename || !(*filename))
1072                 return NULL;
1073
1074         /* MSDOS uses tilde for short versions of long file names, so skip it. */
1075 #ifndef WIN32
1076
1077         /* try tilde expansion */
1078         if (**filename == '~')
1079         {
1080                 char       *fn;
1081                 char            oldp,
1082                                    *p;
1083                 struct passwd *pw;
1084                 char            home[MAXPGPATH];
1085
1086                 fn = *filename;
1087                 *home = '\0';
1088
1089                 p = fn + 1;
1090                 while (*p != '/' && *p != '\0')
1091                         p++;
1092
1093                 oldp = *p;
1094                 *p = '\0';
1095
1096                 if (*(fn + 1) == '\0')
1097                         get_home_path(home);
1098                 else if ((pw = getpwnam(fn + 1)) != NULL)
1099                         StrNCpy(home, pw->pw_dir, MAXPGPATH);
1100
1101                 *p = oldp;
1102                 if (strlen(home) != 0)
1103                 {
1104                         char       *newfn;
1105
1106                         newfn = pg_malloc(strlen(home) + strlen(p) + 1);
1107                         strcpy(newfn, home);
1108                         strcat(newfn, p);
1109
1110                         free(fn);
1111                         *filename = newfn;
1112                 }
1113         }
1114 #endif
1115
1116         return *filename;
1117 }