]> granicus.if.org Git - postgresql/blob - src/bin/psql/common.c
3dea92c7d8f3bb6868754746f7cc1290713ca885
[postgresql] / src / bin / psql / common.c
1 /*
2  * psql - the PostgreSQL interactive terminal
3  *
4  * Copyright (c) 2000-2013, PostgreSQL Global Development Group
5  *
6  * src/bin/psql/common.c
7  */
8 #include "postgres_fe.h"
9 #include "common.h"
10
11 #include <ctype.h>
12 #include <signal.h>
13 #ifndef WIN32
14 #include <unistd.h>                             /* for write() */
15 #else
16 #include <io.h>                                 /* for _write() */
17 #include <win32.h>
18 #endif
19
20 #include "portability/instr_time.h"
21
22 #include "settings.h"
23 #include "command.h"
24 #include "copy.h"
25 #include "mbprint.h"
26
27
28
29 static bool ExecQueryUsingCursor(const char *query, double *elapsed_msec);
30 static bool command_no_begin(const char *query);
31 static bool is_select_command(const char *query);
32
33 /*
34  * setQFout
35  * -- handler for -o command line option and \o command
36  *
37  * Tries to open file fname (or pipe if fname starts with '|')
38  * and stores the file handle in pset)
39  * Upon failure, sets stdout and returns false.
40  */
41 bool
42 setQFout(const char *fname)
43 {
44         bool            status = true;
45
46         /* Close old file/pipe */
47         if (pset.queryFout && pset.queryFout != stdout && pset.queryFout != stderr)
48         {
49                 if (pset.queryFoutPipe)
50                         pclose(pset.queryFout);
51                 else
52                         fclose(pset.queryFout);
53         }
54
55         /* If no filename, set stdout */
56         if (!fname || fname[0] == '\0')
57         {
58                 pset.queryFout = stdout;
59                 pset.queryFoutPipe = false;
60         }
61         else if (*fname == '|')
62         {
63                 pset.queryFout = popen(fname + 1, "w");
64                 pset.queryFoutPipe = true;
65         }
66         else
67         {
68                 pset.queryFout = fopen(fname, "w");
69                 pset.queryFoutPipe = false;
70         }
71
72         if (!(pset.queryFout))
73         {
74                 psql_error("%s: %s\n", fname, strerror(errno));
75                 pset.queryFout = stdout;
76                 pset.queryFoutPipe = false;
77                 status = false;
78         }
79
80         /* Direct signals */
81 #ifndef WIN32
82         pqsignal(SIGPIPE, pset.queryFoutPipe ? SIG_IGN : SIG_DFL);
83 #endif
84
85         return status;
86 }
87
88
89
90 /*
91  * Error reporting for scripts. Errors should look like
92  *       psql:filename:lineno: message
93  *
94  */
95 void
96 psql_error(const char *fmt,...)
97 {
98         va_list         ap;
99
100         fflush(stdout);
101         if (pset.queryFout && pset.queryFout != stdout)
102                 fflush(pset.queryFout);
103
104         if (pset.inputfile)
105                 fprintf(stderr, "%s:%s:" UINT64_FORMAT ": ", pset.progname, pset.inputfile, pset.lineno);
106         va_start(ap, fmt);
107         vfprintf(stderr, _(fmt), ap);
108         va_end(ap);
109 }
110
111
112
113 /*
114  * for backend Notice messages (INFO, WARNING, etc)
115  */
116 void
117 NoticeProcessor(void *arg, const char *message)
118 {
119         (void) arg;                                     /* not used */
120         psql_error("%s", message);
121 }
122
123
124
125 /*
126  * Code to support query cancellation
127  *
128  * Before we start a query, we enable the SIGINT signal catcher to send a
129  * cancel request to the backend. Note that sending the cancel directly from
130  * the signal handler is safe because PQcancel() is written to make it
131  * so. We use write() to report to stderr because it's better to use simple
132  * facilities in a signal handler.
133  *
134  * On win32, the signal canceling happens on a separate thread, because
135  * that's how SetConsoleCtrlHandler works. The PQcancel function is safe
136  * for this (unlike PQrequestCancel). However, a CRITICAL_SECTION is required
137  * to protect the PGcancel structure against being changed while the signal
138  * thread is using it.
139  *
140  * SIGINT is supposed to abort all long-running psql operations, not only
141  * database queries.  In most places, this is accomplished by checking
142  * cancel_pressed during long-running loops.  However, that won't work when
143  * blocked on user input (in readline() or fgets()).  In those places, we
144  * set sigint_interrupt_enabled TRUE while blocked, instructing the signal
145  * catcher to longjmp through sigint_interrupt_jmp.  We assume readline and
146  * fgets are coded to handle possible interruption.  (XXX currently this does
147  * not work on win32, so control-C is less useful there)
148  */
149 volatile bool sigint_interrupt_enabled = false;
150
151 sigjmp_buf      sigint_interrupt_jmp;
152
153 static PGcancel *volatile cancelConn = NULL;
154
155 #ifdef WIN32
156 static CRITICAL_SECTION cancelConnLock;
157 #endif
158
159 /* Used from signal handlers, no buffering */
160 #define write_stderr(str)       write(fileno(stderr), str, strlen(str))
161
162
163 #ifndef WIN32
164
165 static void
166 handle_sigint(SIGNAL_ARGS)
167 {
168         int                     save_errno = errno;
169         int                     rc;
170         char            errbuf[256];
171
172         /* if we are waiting for input, longjmp out of it */
173         if (sigint_interrupt_enabled)
174         {
175                 sigint_interrupt_enabled = false;
176                 siglongjmp(sigint_interrupt_jmp, 1);
177         }
178
179         /* else, set cancel flag to stop any long-running loops */
180         cancel_pressed = true;
181
182         /* and send QueryCancel if we are processing a database query */
183         if (cancelConn != NULL)
184         {
185                 if (PQcancel(cancelConn, errbuf, sizeof(errbuf)))
186                 {
187                         rc = write_stderr("Cancel request sent\n");
188                         (void) rc;                      /* ignore errors, nothing we can do here */
189                 }
190                 else
191                 {
192                         rc = write_stderr("Could not send cancel request: ");
193                         (void) rc;                      /* ignore errors, nothing we can do here */
194                         rc = write_stderr(errbuf);
195                         (void) rc;                      /* ignore errors, nothing we can do here */
196                 }
197         }
198
199         errno = save_errno;                     /* just in case the write changed it */
200 }
201
202 void
203 setup_cancel_handler(void)
204 {
205         pqsignal(SIGINT, handle_sigint);
206 }
207 #else                                                   /* WIN32 */
208
209 static BOOL WINAPI
210 consoleHandler(DWORD dwCtrlType)
211 {
212         char            errbuf[256];
213
214         if (dwCtrlType == CTRL_C_EVENT ||
215                 dwCtrlType == CTRL_BREAK_EVENT)
216         {
217                 /*
218                  * Can't longjmp here, because we are in wrong thread :-(
219                  */
220
221                 /* set cancel flag to stop any long-running loops */
222                 cancel_pressed = true;
223
224                 /* and send QueryCancel if we are processing a database query */
225                 EnterCriticalSection(&cancelConnLock);
226                 if (cancelConn != NULL)
227                 {
228                         if (PQcancel(cancelConn, errbuf, sizeof(errbuf)))
229                                 write_stderr("Cancel request sent\n");
230                         else
231                         {
232                                 write_stderr("Could not send cancel request: ");
233                                 write_stderr(errbuf);
234                         }
235                 }
236                 LeaveCriticalSection(&cancelConnLock);
237
238                 return TRUE;
239         }
240         else
241                 /* Return FALSE for any signals not being handled */
242                 return FALSE;
243 }
244
245 void
246 setup_cancel_handler(void)
247 {
248         InitializeCriticalSection(&cancelConnLock);
249
250         SetConsoleCtrlHandler(consoleHandler, TRUE);
251 }
252 #endif   /* WIN32 */
253
254
255 /* ConnectionUp
256  *
257  * Returns whether our backend connection is still there.
258  */
259 static bool
260 ConnectionUp(void)
261 {
262         return PQstatus(pset.db) != CONNECTION_BAD;
263 }
264
265
266
267 /* CheckConnection
268  *
269  * Verify that we still have a good connection to the backend, and if not,
270  * see if it can be restored.
271  *
272  * Returns true if either the connection was still there, or it could be
273  * restored successfully; false otherwise.      If, however, there was no
274  * connection and the session is non-interactive, this will exit the program
275  * with a code of EXIT_BADCONN.
276  */
277 static bool
278 CheckConnection(void)
279 {
280         bool            OK;
281
282         OK = ConnectionUp();
283         if (!OK)
284         {
285                 if (!pset.cur_cmd_interactive)
286                 {
287                         psql_error("connection to server was lost\n");
288                         exit(EXIT_BADCONN);
289                 }
290
291                 psql_error("The connection to the server was lost. Attempting reset: ");
292                 PQreset(pset.db);
293                 OK = ConnectionUp();
294                 if (!OK)
295                 {
296                         psql_error("Failed.\n");
297                         PQfinish(pset.db);
298                         pset.db = NULL;
299                         ResetCancelConn();
300                         UnsyncVariables();
301                 }
302                 else
303                         psql_error("Succeeded.\n");
304         }
305
306         return OK;
307 }
308
309
310
311 /*
312  * SetCancelConn
313  *
314  * Set cancelConn to point to the current database connection.
315  */
316 void
317 SetCancelConn(void)
318 {
319         PGcancel   *oldCancelConn;
320
321 #ifdef WIN32
322         EnterCriticalSection(&cancelConnLock);
323 #endif
324
325         /* Free the old one if we have one */
326         oldCancelConn = cancelConn;
327         /* be sure handle_sigint doesn't use pointer while freeing */
328         cancelConn = NULL;
329
330         if (oldCancelConn != NULL)
331                 PQfreeCancel(oldCancelConn);
332
333         cancelConn = PQgetCancel(pset.db);
334
335 #ifdef WIN32
336         LeaveCriticalSection(&cancelConnLock);
337 #endif
338 }
339
340
341 /*
342  * ResetCancelConn
343  *
344  * Free the current cancel connection, if any, and set to NULL.
345  */
346 void
347 ResetCancelConn(void)
348 {
349         PGcancel   *oldCancelConn;
350
351 #ifdef WIN32
352         EnterCriticalSection(&cancelConnLock);
353 #endif
354
355         oldCancelConn = cancelConn;
356         /* be sure handle_sigint doesn't use pointer while freeing */
357         cancelConn = NULL;
358
359         if (oldCancelConn != NULL)
360                 PQfreeCancel(oldCancelConn);
361
362 #ifdef WIN32
363         LeaveCriticalSection(&cancelConnLock);
364 #endif
365 }
366
367
368 /*
369  * AcceptResult
370  *
371  * Checks whether a result is valid, giving an error message if necessary;
372  * and ensures that the connection to the backend is still up.
373  *
374  * Returns true for valid result, false for error state.
375  */
376 static bool
377 AcceptResult(const PGresult *result)
378 {
379         bool            OK;
380
381         if (!result)
382                 OK = false;
383         else
384                 switch (PQresultStatus(result))
385                 {
386                         case PGRES_COMMAND_OK:
387                         case PGRES_TUPLES_OK:
388                         case PGRES_EMPTY_QUERY:
389                         case PGRES_COPY_IN:
390                         case PGRES_COPY_OUT:
391                                 /* Fine, do nothing */
392                                 OK = true;
393                                 break;
394
395                         case PGRES_BAD_RESPONSE:
396                         case PGRES_NONFATAL_ERROR:
397                         case PGRES_FATAL_ERROR:
398                                 OK = false;
399                                 break;
400
401                         default:
402                                 OK = false;
403                                 psql_error("unexpected PQresultStatus: %d\n",
404                                                    PQresultStatus(result));
405                                 break;
406                 }
407
408         if (!OK)
409         {
410                 const char *error = PQerrorMessage(pset.db);
411
412                 if (strlen(error))
413                         psql_error("%s", error);
414
415                 CheckConnection();
416         }
417
418         return OK;
419 }
420
421
422
423 /*
424  * PSQLexec
425  *
426  * This is the way to send "backdoor" queries (those not directly entered
427  * by the user). It is subject to -E but not -e.
428  *
429  * In autocommit-off mode, a new transaction block is started if start_xact
430  * is true; nothing special is done when start_xact is false.  Typically,
431  * start_xact = false is used for SELECTs and explicit BEGIN/COMMIT commands.
432  *
433  * Caller is responsible for handling the ensuing processing if a COPY
434  * command is sent.
435  *
436  * Note: we don't bother to check PQclientEncoding; it is assumed that no
437  * caller uses this path to issue "SET CLIENT_ENCODING".
438  */
439 PGresult *
440 PSQLexec(const char *query, bool start_xact)
441 {
442         PGresult   *res;
443
444         if (!pset.db)
445         {
446                 psql_error("You are currently not connected to a database.\n");
447                 return NULL;
448         }
449
450         if (pset.echo_hidden != PSQL_ECHO_HIDDEN_OFF)
451         {
452                 printf(_("********* QUERY **********\n"
453                                  "%s\n"
454                                  "**************************\n\n"), query);
455                 fflush(stdout);
456                 if (pset.logfile)
457                 {
458                         fprintf(pset.logfile,
459                                         _("********* QUERY **********\n"
460                                           "%s\n"
461                                           "**************************\n\n"), query);
462                         fflush(pset.logfile);
463                 }
464
465                 if (pset.echo_hidden == PSQL_ECHO_HIDDEN_NOEXEC)
466                         return NULL;
467         }
468
469         SetCancelConn();
470
471         if (start_xact &&
472                 !pset.autocommit &&
473                 PQtransactionStatus(pset.db) == PQTRANS_IDLE)
474         {
475                 res = PQexec(pset.db, "BEGIN");
476                 if (PQresultStatus(res) != PGRES_COMMAND_OK)
477                 {
478                         psql_error("%s", PQerrorMessage(pset.db));
479                         PQclear(res);
480                         ResetCancelConn();
481                         return NULL;
482                 }
483                 PQclear(res);
484         }
485
486         res = PQexec(pset.db, query);
487
488         ResetCancelConn();
489
490         if (!AcceptResult(res))
491         {
492                 PQclear(res);
493                 res = NULL;
494         }
495
496         return res;
497 }
498
499
500
501 /*
502  * PrintNotifications: check for asynchronous notifications, and print them out
503  */
504 static void
505 PrintNotifications(void)
506 {
507         PGnotify   *notify;
508
509         while ((notify = PQnotifies(pset.db)))
510         {
511                 /* for backward compatibility, only show payload if nonempty */
512                 if (notify->extra[0])
513                         fprintf(pset.queryFout, _("Asynchronous notification \"%s\" with payload \"%s\" received from server process with PID %d.\n"),
514                                         notify->relname, notify->extra, notify->be_pid);
515                 else
516                         fprintf(pset.queryFout, _("Asynchronous notification \"%s\" received from server process with PID %d.\n"),
517                                         notify->relname, notify->be_pid);
518                 fflush(pset.queryFout);
519                 PQfreemem(notify);
520         }
521 }
522
523
524 /*
525  * PrintQueryTuples: assuming query result is OK, print its tuples
526  *
527  * Returns true if successful, false otherwise.
528  */
529 static bool
530 PrintQueryTuples(const PGresult *results)
531 {
532         printQueryOpt my_popt = pset.popt;
533
534         /* write output to \g argument, if any */
535         if (pset.gfname)
536         {
537                 /* keep this code in sync with ExecQueryUsingCursor */
538                 FILE       *queryFout_copy = pset.queryFout;
539                 bool            queryFoutPipe_copy = pset.queryFoutPipe;
540
541                 pset.queryFout = stdout;        /* so it doesn't get closed */
542
543                 /* open file/pipe */
544                 if (!setQFout(pset.gfname))
545                 {
546                         pset.queryFout = queryFout_copy;
547                         pset.queryFoutPipe = queryFoutPipe_copy;
548                         return false;
549                 }
550
551                 printQuery(results, &my_popt, pset.queryFout, pset.logfile);
552
553                 /* close file/pipe, restore old setting */
554                 setQFout(NULL);
555
556                 pset.queryFout = queryFout_copy;
557                 pset.queryFoutPipe = queryFoutPipe_copy;
558         }
559         else
560                 printQuery(results, &my_popt, pset.queryFout, pset.logfile);
561
562         return true;
563 }
564
565
566 /*
567  * StoreQueryTuple: assuming query result is OK, save data into variables
568  *
569  * Returns true if successful, false otherwise.
570  */
571 static bool
572 StoreQueryTuple(const PGresult *result)
573 {
574         bool            success = true;
575
576         if (PQntuples(result) < 1)
577         {
578                 psql_error("no rows returned for \\gset\n");
579                 success = false;
580         }
581         else if (PQntuples(result) > 1)
582         {
583                 psql_error("more than one row returned for \\gset\n");
584                 success = false;
585         }
586         else
587         {
588                 int                     i;
589
590                 for (i = 0; i < PQnfields(result); i++)
591                 {
592                         char       *colname = PQfname(result, i);
593                         char       *varname;
594                         char       *value;
595
596                         /* concate prefix and column name */
597                         varname = pg_malloc(strlen(pset.gset_prefix) + strlen(colname) + 1);
598                         strcpy(varname, pset.gset_prefix);
599                         strcat(varname, colname);
600
601                         if (!PQgetisnull(result, 0, i))
602                                 value = PQgetvalue(result, 0, i);
603                         else
604                         {
605                                 /* for NULL value, unset rather than set the variable */
606                                 value = NULL;
607                         }
608
609                         if (!SetVariable(pset.vars, varname, value))
610                         {
611                                 psql_error("could not set variable \"%s\"\n", varname);
612                                 free(varname);
613                                 success = false;
614                                 break;
615                         }
616
617                         free(varname);
618                 }
619         }
620
621         return success;
622 }
623
624
625 /*
626  * ProcessResult: utility function for use by SendQuery() only
627  *
628  * When our command string contained a COPY FROM STDIN or COPY TO STDOUT,
629  * PQexec() has stopped at the PGresult associated with the first such
630  * command.  In that event, we'll marshal data for the COPY and then cycle
631  * through any subsequent PGresult objects.
632  *
633  * When the command string contained no affected COPY command, this function
634  * degenerates to an AcceptResult() call.
635  *
636  * Changes its argument to point to the last PGresult of the command string,
637  * or NULL if that result was for a COPY FROM STDIN or COPY TO STDOUT.
638  *
639  * Returns true on complete success, false otherwise.  Possible failure modes
640  * include purely client-side problems; check the transaction status for the
641  * server-side opinion.
642  */
643 static bool
644 ProcessResult(PGresult **results)
645 {
646         PGresult   *next_result;
647         bool            success = true;
648         bool            first_cycle = true;
649
650         do
651         {
652                 ExecStatusType result_status;
653                 bool            is_copy;
654
655                 if (!AcceptResult(*results))
656                 {
657                         /*
658                          * Failure at this point is always a server-side failure or a
659                          * failure to submit the command string.  Either way, we're
660                          * finished with this command string.
661                          */
662                         success = false;
663                         break;
664                 }
665
666                 result_status = PQresultStatus(*results);
667                 switch (result_status)
668                 {
669                         case PGRES_EMPTY_QUERY:
670                         case PGRES_COMMAND_OK:
671                         case PGRES_TUPLES_OK:
672                                 is_copy = false;
673                                 break;
674
675                         case PGRES_COPY_OUT:
676                         case PGRES_COPY_IN:
677                                 is_copy = true;
678                                 break;
679
680                         default:
681                                 /* AcceptResult() should have caught anything else. */
682                                 is_copy = false;
683                                 psql_error("unexpected PQresultStatus: %d\n", result_status);
684                                 break;
685                 }
686
687                 if (is_copy)
688                 {
689                         /*
690                          * Marshal the COPY data.  Either subroutine will get the
691                          * connection out of its COPY state, then call PQresultStatus()
692                          * once and report any error.
693                          */
694                         SetCancelConn();
695                         if (result_status == PGRES_COPY_OUT)
696                                 success = handleCopyOut(pset.db, pset.queryFout) && success;
697                         else
698                                 success = handleCopyIn(pset.db, pset.cur_cmd_source,
699                                                                            PQbinaryTuples(*results)) && success;
700                         ResetCancelConn();
701
702                         /*
703                          * Call PQgetResult() once more.  In the typical case of a
704                          * single-command string, it will return NULL.  Otherwise, we'll
705                          * have other results to process that may include other COPYs.
706                          */
707                         PQclear(*results);
708                         *results = next_result = PQgetResult(pset.db);
709                 }
710                 else if (first_cycle)
711                         /* fast path: no COPY commands; PQexec visited all results */
712                         break;
713                 else if ((next_result = PQgetResult(pset.db)))
714                 {
715                         /* non-COPY command(s) after a COPY: keep the last one */
716                         PQclear(*results);
717                         *results = next_result;
718                 }
719
720                 first_cycle = false;
721         } while (next_result);
722
723         /* may need this to recover from conn loss during COPY */
724         if (!first_cycle && !CheckConnection())
725                 return false;
726
727         return success;
728 }
729
730
731 /*
732  * PrintQueryStatus: report command status as required
733  *
734  * Note: Utility function for use by PrintQueryResults() only.
735  */
736 static void
737 PrintQueryStatus(PGresult *results)
738 {
739         char            buf[16];
740
741         if (!pset.quiet)
742         {
743                 if (pset.popt.topt.format == PRINT_HTML)
744                 {
745                         fputs("<p>", pset.queryFout);
746                         html_escaped_print(PQcmdStatus(results), pset.queryFout);
747                         fputs("</p>\n", pset.queryFout);
748                 }
749                 else
750                         fprintf(pset.queryFout, "%s\n", PQcmdStatus(results));
751         }
752
753         if (pset.logfile)
754                 fprintf(pset.logfile, "%s\n", PQcmdStatus(results));
755
756         snprintf(buf, sizeof(buf), "%u", (unsigned int) PQoidValue(results));
757         SetVariable(pset.vars, "LASTOID", buf);
758 }
759
760
761 /*
762  * PrintQueryResults: print out (or store) query results as required
763  *
764  * Note: Utility function for use by SendQuery() only.
765  *
766  * Returns true if the query executed successfully, false otherwise.
767  */
768 static bool
769 PrintQueryResults(PGresult *results)
770 {
771         bool            success;
772         const char *cmdstatus;
773
774         if (!results)
775                 return false;
776
777         switch (PQresultStatus(results))
778         {
779                 case PGRES_TUPLES_OK:
780                         /* store or print the data ... */
781                         if (pset.gset_prefix)
782                                 success = StoreQueryTuple(results);
783                         else
784                                 success = PrintQueryTuples(results);
785                         /* if it's INSERT/UPDATE/DELETE RETURNING, also print status */
786                         cmdstatus = PQcmdStatus(results);
787                         if (strncmp(cmdstatus, "INSERT", 6) == 0 ||
788                                 strncmp(cmdstatus, "UPDATE", 6) == 0 ||
789                                 strncmp(cmdstatus, "DELETE", 6) == 0)
790                                 PrintQueryStatus(results);
791                         break;
792
793                 case PGRES_COMMAND_OK:
794                         PrintQueryStatus(results);
795                         success = true;
796                         break;
797
798                 case PGRES_EMPTY_QUERY:
799                         success = true;
800                         break;
801
802                 case PGRES_COPY_OUT:
803                 case PGRES_COPY_IN:
804                         /* nothing to do here */
805                         success = true;
806                         break;
807
808                 case PGRES_BAD_RESPONSE:
809                 case PGRES_NONFATAL_ERROR:
810                 case PGRES_FATAL_ERROR:
811                         success = false;
812                         break;
813
814                 default:
815                         success = false;
816                         psql_error("unexpected PQresultStatus: %d\n",
817                                            PQresultStatus(results));
818                         break;
819         }
820
821         fflush(pset.queryFout);
822
823         return success;
824 }
825
826
827 /*
828  * SendQuery: send the query string to the backend
829  * (and print out results)
830  *
831  * Note: This is the "front door" way to send a query. That is, use it to
832  * send queries actually entered by the user. These queries will be subject to
833  * single step mode.
834  * To send "back door" queries (generated by slash commands, etc.) in a
835  * controlled way, use PSQLexec().
836  *
837  * Returns true if the query executed successfully, false otherwise.
838  */
839 bool
840 SendQuery(const char *query)
841 {
842         PGresult   *results;
843         PGTransactionStatusType transaction_status;
844         double          elapsed_msec = 0;
845         bool            OK = false;
846         bool            on_error_rollback_savepoint = false;
847         static bool on_error_rollback_warning = false;
848
849         if (!pset.db)
850         {
851                 psql_error("You are currently not connected to a database.\n");
852                 goto sendquery_cleanup;
853         }
854
855         if (pset.singlestep)
856         {
857                 char            buf[3];
858
859                 printf(_("***(Single step mode: verify command)*******************************************\n"
860                                  "%s\n"
861                                  "***(press return to proceed or enter x and return to cancel)********************\n"),
862                            query);
863                 fflush(stdout);
864                 if (fgets(buf, sizeof(buf), stdin) != NULL)
865                         if (buf[0] == 'x')
866                                 goto sendquery_cleanup;
867         }
868         else if (pset.echo == PSQL_ECHO_QUERIES)
869         {
870                 puts(query);
871                 fflush(stdout);
872         }
873
874         if (pset.logfile)
875         {
876                 fprintf(pset.logfile,
877                                 _("********* QUERY **********\n"
878                                   "%s\n"
879                                   "**************************\n\n"), query);
880                 fflush(pset.logfile);
881         }
882
883         SetCancelConn();
884
885         transaction_status = PQtransactionStatus(pset.db);
886
887         if (transaction_status == PQTRANS_IDLE &&
888                 !pset.autocommit &&
889                 !command_no_begin(query))
890         {
891                 results = PQexec(pset.db, "BEGIN");
892                 if (PQresultStatus(results) != PGRES_COMMAND_OK)
893                 {
894                         psql_error("%s", PQerrorMessage(pset.db));
895                         PQclear(results);
896                         ResetCancelConn();
897                         goto sendquery_cleanup;
898                 }
899                 PQclear(results);
900                 transaction_status = PQtransactionStatus(pset.db);
901         }
902
903         if (transaction_status == PQTRANS_INTRANS &&
904                 pset.on_error_rollback != PSQL_ERROR_ROLLBACK_OFF &&
905                 (pset.cur_cmd_interactive ||
906                  pset.on_error_rollback == PSQL_ERROR_ROLLBACK_ON))
907         {
908                 if (on_error_rollback_warning == false && pset.sversion < 80000)
909                 {
910                         psql_error("The server (version %d.%d) does not support savepoints for ON_ERROR_ROLLBACK.\n",
911                                            pset.sversion / 10000, (pset.sversion / 100) % 100);
912                         on_error_rollback_warning = true;
913                 }
914                 else
915                 {
916                         results = PQexec(pset.db, "SAVEPOINT pg_psql_temporary_savepoint");
917                         if (PQresultStatus(results) != PGRES_COMMAND_OK)
918                         {
919                                 psql_error("%s", PQerrorMessage(pset.db));
920                                 PQclear(results);
921                                 ResetCancelConn();
922                                 goto sendquery_cleanup;
923                         }
924                         PQclear(results);
925                         on_error_rollback_savepoint = true;
926                 }
927         }
928
929         if (pset.fetch_count <= 0 || !is_select_command(query))
930         {
931                 /* Default fetch-it-all-and-print mode */
932                 instr_time      before,
933                                         after;
934
935                 if (pset.timing)
936                         INSTR_TIME_SET_CURRENT(before);
937
938                 results = PQexec(pset.db, query);
939
940                 /* these operations are included in the timing result: */
941                 ResetCancelConn();
942                 OK = ProcessResult(&results);
943
944                 if (pset.timing)
945                 {
946                         INSTR_TIME_SET_CURRENT(after);
947                         INSTR_TIME_SUBTRACT(after, before);
948                         elapsed_msec = INSTR_TIME_GET_MILLISEC(after);
949                 }
950
951                 /* but printing results isn't: */
952                 if (OK && results)
953                         OK = PrintQueryResults(results);
954         }
955         else
956         {
957                 /* Fetch-in-segments mode */
958                 OK = ExecQueryUsingCursor(query, &elapsed_msec);
959                 ResetCancelConn();
960                 results = NULL;                 /* PQclear(NULL) does nothing */
961         }
962
963         /* If we made a temporary savepoint, possibly release/rollback */
964         if (on_error_rollback_savepoint)
965         {
966                 const char *svptcmd = NULL;
967
968                 transaction_status = PQtransactionStatus(pset.db);
969
970                 switch (transaction_status)
971                 {
972                         case PQTRANS_INERROR:
973                                 /* We always rollback on an error */
974                                 svptcmd = "ROLLBACK TO pg_psql_temporary_savepoint";
975                                 break;
976
977                         case PQTRANS_IDLE:
978                                 /* If they are no longer in a transaction, then do nothing */
979                                 break;
980
981                         case PQTRANS_INTRANS:
982
983                                 /*
984                                  * Do nothing if they are messing with savepoints themselves:
985                                  * If the user did RELEASE or ROLLBACK, our savepoint is gone.
986                                  * If they issued a SAVEPOINT, releasing ours would remove
987                                  * theirs.
988                                  */
989                                 if (results &&
990                                         (strcmp(PQcmdStatus(results), "SAVEPOINT") == 0 ||
991                                          strcmp(PQcmdStatus(results), "RELEASE") == 0 ||
992                                          strcmp(PQcmdStatus(results), "ROLLBACK") == 0))
993                                         svptcmd = NULL;
994                                 else
995                                         svptcmd = "RELEASE pg_psql_temporary_savepoint";
996                                 break;
997
998                         case PQTRANS_ACTIVE:
999                         case PQTRANS_UNKNOWN:
1000                         default:
1001                                 OK = false;
1002                                 /* PQTRANS_UNKNOWN is expected given a broken connection. */
1003                                 if (transaction_status != PQTRANS_UNKNOWN || ConnectionUp())
1004                                         psql_error("unexpected transaction status (%d)\n",
1005                                                            transaction_status);
1006                                 break;
1007                 }
1008
1009                 if (svptcmd)
1010                 {
1011                         PGresult   *svptres;
1012
1013                         svptres = PQexec(pset.db, svptcmd);
1014                         if (PQresultStatus(svptres) != PGRES_COMMAND_OK)
1015                         {
1016                                 psql_error("%s", PQerrorMessage(pset.db));
1017                                 PQclear(svptres);
1018                                 OK = false;
1019
1020                                 PQclear(results);
1021                                 ResetCancelConn();
1022                                 goto sendquery_cleanup;
1023                         }
1024                         PQclear(svptres);
1025                 }
1026         }
1027
1028         PQclear(results);
1029
1030         /* Possible microtiming output */
1031         if (pset.timing)
1032                 printf(_("Time: %.3f ms\n"), elapsed_msec);
1033
1034         /* check for events that may occur during query execution */
1035
1036         if (pset.encoding != PQclientEncoding(pset.db) &&
1037                 PQclientEncoding(pset.db) >= 0)
1038         {
1039                 /* track effects of SET CLIENT_ENCODING */
1040                 pset.encoding = PQclientEncoding(pset.db);
1041                 pset.popt.topt.encoding = pset.encoding;
1042                 SetVariable(pset.vars, "ENCODING",
1043                                         pg_encoding_to_char(pset.encoding));
1044         }
1045
1046         PrintNotifications();
1047
1048         /* perform cleanup that should occur after any attempted query */
1049
1050 sendquery_cleanup:
1051
1052         /* reset \g's output-to-filename trigger */
1053         if (pset.gfname)
1054         {
1055                 free(pset.gfname);
1056                 pset.gfname = NULL;
1057         }
1058
1059         /* reset \gset trigger */
1060         if (pset.gset_prefix)
1061         {
1062                 free(pset.gset_prefix);
1063                 pset.gset_prefix = NULL;
1064         }
1065
1066         return OK;
1067 }
1068
1069
1070 /*
1071  * ExecQueryUsingCursor: run a SELECT-like query using a cursor
1072  *
1073  * This feature allows result sets larger than RAM to be dealt with.
1074  *
1075  * Returns true if the query executed successfully, false otherwise.
1076  *
1077  * If pset.timing is on, total query time (exclusive of result-printing) is
1078  * stored into *elapsed_msec.
1079  */
1080 static bool
1081 ExecQueryUsingCursor(const char *query, double *elapsed_msec)
1082 {
1083         bool            OK = true;
1084         PGresult   *results;
1085         PQExpBufferData buf;
1086         printQueryOpt my_popt = pset.popt;
1087         FILE       *queryFout_copy = pset.queryFout;
1088         bool            queryFoutPipe_copy = pset.queryFoutPipe;
1089         bool            started_txn = false;
1090         bool            did_pager = false;
1091         int                     ntuples;
1092         int                     fetch_count;
1093         char            fetch_cmd[64];
1094         instr_time      before,
1095                                 after;
1096         int                     flush_error;
1097
1098         *elapsed_msec = 0;
1099
1100         /* initialize print options for partial table output */
1101         my_popt.topt.start_table = true;
1102         my_popt.topt.stop_table = false;
1103         my_popt.topt.prior_records = 0;
1104
1105         if (pset.timing)
1106                 INSTR_TIME_SET_CURRENT(before);
1107
1108         /* if we're not in a transaction, start one */
1109         if (PQtransactionStatus(pset.db) == PQTRANS_IDLE)
1110         {
1111                 results = PQexec(pset.db, "BEGIN");
1112                 OK = AcceptResult(results) &&
1113                         (PQresultStatus(results) == PGRES_COMMAND_OK);
1114                 PQclear(results);
1115                 if (!OK)
1116                         return false;
1117                 started_txn = true;
1118         }
1119
1120         /* Send DECLARE CURSOR */
1121         initPQExpBuffer(&buf);
1122         appendPQExpBuffer(&buf, "DECLARE _psql_cursor NO SCROLL CURSOR FOR\n%s",
1123                                           query);
1124
1125         results = PQexec(pset.db, buf.data);
1126         OK = AcceptResult(results) &&
1127                 (PQresultStatus(results) == PGRES_COMMAND_OK);
1128         PQclear(results);
1129         termPQExpBuffer(&buf);
1130         if (!OK)
1131                 goto cleanup;
1132
1133         if (pset.timing)
1134         {
1135                 INSTR_TIME_SET_CURRENT(after);
1136                 INSTR_TIME_SUBTRACT(after, before);
1137                 *elapsed_msec += INSTR_TIME_GET_MILLISEC(after);
1138         }
1139
1140         /*
1141          * In \gset mode, we force the fetch count to be 2, so that we will throw
1142          * the appropriate error if the query returns more than one row.
1143          */
1144         if (pset.gset_prefix)
1145                 fetch_count = 2;
1146         else
1147                 fetch_count = pset.fetch_count;
1148
1149         snprintf(fetch_cmd, sizeof(fetch_cmd),
1150                          "FETCH FORWARD %d FROM _psql_cursor",
1151                          fetch_count);
1152
1153         /* prepare to write output to \g argument, if any */
1154         if (pset.gfname)
1155         {
1156                 /* keep this code in sync with PrintQueryTuples */
1157                 pset.queryFout = stdout;        /* so it doesn't get closed */
1158
1159                 /* open file/pipe */
1160                 if (!setQFout(pset.gfname))
1161                 {
1162                         pset.queryFout = queryFout_copy;
1163                         pset.queryFoutPipe = queryFoutPipe_copy;
1164                         OK = false;
1165                         goto cleanup;
1166                 }
1167         }
1168
1169         /* clear any pre-existing error indication on the output stream */
1170         clearerr(pset.queryFout);
1171
1172         for (;;)
1173         {
1174                 if (pset.timing)
1175                         INSTR_TIME_SET_CURRENT(before);
1176
1177                 /* get fetch_count tuples at a time */
1178                 results = PQexec(pset.db, fetch_cmd);
1179
1180                 if (pset.timing)
1181                 {
1182                         INSTR_TIME_SET_CURRENT(after);
1183                         INSTR_TIME_SUBTRACT(after, before);
1184                         *elapsed_msec += INSTR_TIME_GET_MILLISEC(after);
1185                 }
1186
1187                 if (PQresultStatus(results) != PGRES_TUPLES_OK)
1188                 {
1189                         /* shut down pager before printing error message */
1190                         if (did_pager)
1191                         {
1192                                 ClosePager(pset.queryFout);
1193                                 pset.queryFout = queryFout_copy;
1194                                 pset.queryFoutPipe = queryFoutPipe_copy;
1195                                 did_pager = false;
1196                         }
1197
1198                         OK = AcceptResult(results);
1199                         Assert(!OK);
1200                         PQclear(results);
1201                         break;
1202                 }
1203
1204                 if (pset.gset_prefix)
1205                 {
1206                         /* StoreQueryTuple will complain if not exactly one row */
1207                         OK = StoreQueryTuple(results);
1208                         PQclear(results);
1209                         break;
1210                 }
1211
1212                 ntuples = PQntuples(results);
1213
1214                 if (ntuples < fetch_count)
1215                 {
1216                         /* this is the last result set, so allow footer decoration */
1217                         my_popt.topt.stop_table = true;
1218                 }
1219                 else if (pset.queryFout == stdout && !did_pager)
1220                 {
1221                         /*
1222                          * If query requires multiple result sets, hack to ensure that
1223                          * only one pager instance is used for the whole mess
1224                          */
1225                         pset.queryFout = PageOutput(100000, my_popt.topt.pager);
1226                         did_pager = true;
1227                 }
1228
1229                 printQuery(results, &my_popt, pset.queryFout, pset.logfile);
1230
1231                 PQclear(results);
1232
1233                 /* after the first result set, disallow header decoration */
1234                 my_popt.topt.start_table = false;
1235                 my_popt.topt.prior_records += ntuples;
1236
1237                 /*
1238                  * Make sure to flush the output stream, so intermediate results are
1239                  * visible to the client immediately.  We check the results because if
1240                  * the pager dies/exits/etc, there's no sense throwing more data at
1241                  * it.
1242                  */
1243                 flush_error = fflush(pset.queryFout);
1244
1245                 /*
1246                  * Check if we are at the end, if a cancel was pressed, or if there
1247                  * were any errors either trying to flush out the results, or more
1248                  * generally on the output stream at all.  If we hit any errors
1249                  * writing things to the stream, we presume $PAGER has disappeared and
1250                  * stop bothering to pull down more data.
1251                  */
1252                 if (ntuples < fetch_count || cancel_pressed || flush_error ||
1253                         ferror(pset.queryFout))
1254                         break;
1255         }
1256
1257         /* close \g argument file/pipe, restore old setting */
1258         if (pset.gfname)
1259         {
1260                 /* keep this code in sync with PrintQueryTuples */
1261                 setQFout(NULL);
1262
1263                 pset.queryFout = queryFout_copy;
1264                 pset.queryFoutPipe = queryFoutPipe_copy;
1265         }
1266         else if (did_pager)
1267         {
1268                 ClosePager(pset.queryFout);
1269                 pset.queryFout = queryFout_copy;
1270                 pset.queryFoutPipe = queryFoutPipe_copy;
1271         }
1272
1273 cleanup:
1274         if (pset.timing)
1275                 INSTR_TIME_SET_CURRENT(before);
1276
1277         /*
1278          * We try to close the cursor on either success or failure, but on failure
1279          * ignore the result (it's probably just a bleat about being in an aborted
1280          * transaction)
1281          */
1282         results = PQexec(pset.db, "CLOSE _psql_cursor");
1283         if (OK)
1284         {
1285                 OK = AcceptResult(results) &&
1286                         (PQresultStatus(results) == PGRES_COMMAND_OK);
1287         }
1288         PQclear(results);
1289
1290         if (started_txn)
1291         {
1292                 results = PQexec(pset.db, OK ? "COMMIT" : "ROLLBACK");
1293                 OK &= AcceptResult(results) &&
1294                         (PQresultStatus(results) == PGRES_COMMAND_OK);
1295                 PQclear(results);
1296         }
1297
1298         if (pset.timing)
1299         {
1300                 INSTR_TIME_SET_CURRENT(after);
1301                 INSTR_TIME_SUBTRACT(after, before);
1302                 *elapsed_msec += INSTR_TIME_GET_MILLISEC(after);
1303         }
1304
1305         return OK;
1306 }
1307
1308
1309 /*
1310  * Advance the given char pointer over white space and SQL comments.
1311  */
1312 static const char *
1313 skip_white_space(const char *query)
1314 {
1315         int                     cnestlevel = 0; /* slash-star comment nest level */
1316
1317         while (*query)
1318         {
1319                 int                     mblen = PQmblen(query, pset.encoding);
1320
1321                 /*
1322                  * Note: we assume the encoding is a superset of ASCII, so that for
1323                  * example "query[0] == '/'" is meaningful.  However, we do NOT assume
1324                  * that the second and subsequent bytes of a multibyte character
1325                  * couldn't look like ASCII characters; so it is critical to advance
1326                  * by mblen, not 1, whenever we haven't exactly identified the
1327                  * character we are skipping over.
1328                  */
1329                 if (isspace((unsigned char) *query))
1330                         query += mblen;
1331                 else if (query[0] == '/' && query[1] == '*')
1332                 {
1333                         cnestlevel++;
1334                         query += 2;
1335                 }
1336                 else if (cnestlevel > 0 && query[0] == '*' && query[1] == '/')
1337                 {
1338                         cnestlevel--;
1339                         query += 2;
1340                 }
1341                 else if (cnestlevel == 0 && query[0] == '-' && query[1] == '-')
1342                 {
1343                         query += 2;
1344
1345                         /*
1346                          * We have to skip to end of line since any slash-star inside the
1347                          * -- comment does NOT start a slash-star comment.
1348                          */
1349                         while (*query)
1350                         {
1351                                 if (*query == '\n')
1352                                 {
1353                                         query++;
1354                                         break;
1355                                 }
1356                                 query += PQmblen(query, pset.encoding);
1357                         }
1358                 }
1359                 else if (cnestlevel > 0)
1360                         query += mblen;
1361                 else
1362                         break;                          /* found first token */
1363         }
1364
1365         return query;
1366 }
1367
1368
1369 /*
1370  * Check whether a command is one of those for which we should NOT start
1371  * a new transaction block (ie, send a preceding BEGIN).
1372  *
1373  * These include the transaction control statements themselves, plus
1374  * certain statements that the backend disallows inside transaction blocks.
1375  */
1376 static bool
1377 command_no_begin(const char *query)
1378 {
1379         int                     wordlen;
1380
1381         /*
1382          * First we must advance over any whitespace and comments.
1383          */
1384         query = skip_white_space(query);
1385
1386         /*
1387          * Check word length (since "beginx" is not "begin").
1388          */
1389         wordlen = 0;
1390         while (isalpha((unsigned char) query[wordlen]))
1391                 wordlen += PQmblen(&query[wordlen], pset.encoding);
1392
1393         /*
1394          * Transaction control commands.  These should include every keyword that
1395          * gives rise to a TransactionStmt in the backend grammar, except for the
1396          * savepoint-related commands.
1397          *
1398          * (We assume that START must be START TRANSACTION, since there is
1399          * presently no other "START foo" command.)
1400          */
1401         if (wordlen == 5 && pg_strncasecmp(query, "abort", 5) == 0)
1402                 return true;
1403         if (wordlen == 5 && pg_strncasecmp(query, "begin", 5) == 0)
1404                 return true;
1405         if (wordlen == 5 && pg_strncasecmp(query, "start", 5) == 0)
1406                 return true;
1407         if (wordlen == 6 && pg_strncasecmp(query, "commit", 6) == 0)
1408                 return true;
1409         if (wordlen == 3 && pg_strncasecmp(query, "end", 3) == 0)
1410                 return true;
1411         if (wordlen == 8 && pg_strncasecmp(query, "rollback", 8) == 0)
1412                 return true;
1413         if (wordlen == 7 && pg_strncasecmp(query, "prepare", 7) == 0)
1414         {
1415                 /* PREPARE TRANSACTION is a TC command, PREPARE foo is not */
1416                 query += wordlen;
1417
1418                 query = skip_white_space(query);
1419
1420                 wordlen = 0;
1421                 while (isalpha((unsigned char) query[wordlen]))
1422                         wordlen += PQmblen(&query[wordlen], pset.encoding);
1423
1424                 if (wordlen == 11 && pg_strncasecmp(query, "transaction", 11) == 0)
1425                         return true;
1426                 return false;
1427         }
1428
1429         /*
1430          * Commands not allowed within transactions.  The statements checked for
1431          * here should be exactly those that call PreventTransactionChain() in the
1432          * backend.
1433          */
1434         if (wordlen == 6 && pg_strncasecmp(query, "vacuum", 6) == 0)
1435                 return true;
1436         if (wordlen == 7 && pg_strncasecmp(query, "cluster", 7) == 0)
1437         {
1438                 /* CLUSTER with any arguments is allowed in transactions */
1439                 query += wordlen;
1440
1441                 query = skip_white_space(query);
1442
1443                 if (isalpha((unsigned char) query[0]))
1444                         return false;           /* has additional words */
1445                 return true;                    /* it's CLUSTER without arguments */
1446         }
1447
1448         if (wordlen == 6 && pg_strncasecmp(query, "create", 6) == 0)
1449         {
1450                 query += wordlen;
1451
1452                 query = skip_white_space(query);
1453
1454                 wordlen = 0;
1455                 while (isalpha((unsigned char) query[wordlen]))
1456                         wordlen += PQmblen(&query[wordlen], pset.encoding);
1457
1458                 if (wordlen == 8 && pg_strncasecmp(query, "database", 8) == 0)
1459                         return true;
1460                 if (wordlen == 10 && pg_strncasecmp(query, "tablespace", 10) == 0)
1461                         return true;
1462
1463                 /* CREATE [UNIQUE] INDEX CONCURRENTLY isn't allowed in xacts */
1464                 if (wordlen == 6 && pg_strncasecmp(query, "unique", 6) == 0)
1465                 {
1466                         query += wordlen;
1467
1468                         query = skip_white_space(query);
1469
1470                         wordlen = 0;
1471                         while (isalpha((unsigned char) query[wordlen]))
1472                                 wordlen += PQmblen(&query[wordlen], pset.encoding);
1473                 }
1474
1475                 if (wordlen == 5 && pg_strncasecmp(query, "index", 5) == 0)
1476                 {
1477                         query += wordlen;
1478
1479                         query = skip_white_space(query);
1480
1481                         wordlen = 0;
1482                         while (isalpha((unsigned char) query[wordlen]))
1483                                 wordlen += PQmblen(&query[wordlen], pset.encoding);
1484
1485                         if (wordlen == 12 && pg_strncasecmp(query, "concurrently", 12) == 0)
1486                                 return true;
1487                 }
1488
1489                 return false;
1490         }
1491
1492         /*
1493          * Note: these tests will match DROP SYSTEM and REINDEX TABLESPACE, which
1494          * aren't really valid commands so we don't care much. The other four
1495          * possible matches are correct.
1496          */
1497         if ((wordlen == 4 && pg_strncasecmp(query, "drop", 4) == 0) ||
1498                 (wordlen == 7 && pg_strncasecmp(query, "reindex", 7) == 0))
1499         {
1500                 query += wordlen;
1501
1502                 query = skip_white_space(query);
1503
1504                 wordlen = 0;
1505                 while (isalpha((unsigned char) query[wordlen]))
1506                         wordlen += PQmblen(&query[wordlen], pset.encoding);
1507
1508                 if (wordlen == 8 && pg_strncasecmp(query, "database", 8) == 0)
1509                         return true;
1510                 if (wordlen == 6 && pg_strncasecmp(query, "system", 6) == 0)
1511                         return true;
1512                 if (wordlen == 10 && pg_strncasecmp(query, "tablespace", 10) == 0)
1513                         return true;
1514                 return false;
1515         }
1516
1517         /* DISCARD ALL isn't allowed in xacts, but other variants are allowed. */
1518         if (wordlen == 7 && pg_strncasecmp(query, "discard", 7) == 0)
1519         {
1520                 query += wordlen;
1521
1522                 query = skip_white_space(query);
1523
1524                 wordlen = 0;
1525                 while (isalpha((unsigned char) query[wordlen]))
1526                         wordlen += PQmblen(&query[wordlen], pset.encoding);
1527
1528                 if (wordlen == 3 && pg_strncasecmp(query, "all", 3) == 0)
1529                         return true;
1530                 return false;
1531         }
1532
1533         return false;
1534 }
1535
1536
1537 /*
1538  * Check whether the specified command is a SELECT (or VALUES).
1539  */
1540 static bool
1541 is_select_command(const char *query)
1542 {
1543         int                     wordlen;
1544
1545         /*
1546          * First advance over any whitespace, comments and left parentheses.
1547          */
1548         for (;;)
1549         {
1550                 query = skip_white_space(query);
1551                 if (query[0] == '(')
1552                         query++;
1553                 else
1554                         break;
1555         }
1556
1557         /*
1558          * Check word length (since "selectx" is not "select").
1559          */
1560         wordlen = 0;
1561         while (isalpha((unsigned char) query[wordlen]))
1562                 wordlen += PQmblen(&query[wordlen], pset.encoding);
1563
1564         if (wordlen == 6 && pg_strncasecmp(query, "select", 6) == 0)
1565                 return true;
1566
1567         if (wordlen == 6 && pg_strncasecmp(query, "values", 6) == 0)
1568                 return true;
1569
1570         return false;
1571 }
1572
1573
1574 /*
1575  * Test if the current user is a database superuser.
1576  *
1577  * Note: this will correctly detect superuserness only with a protocol-3.0
1578  * or newer backend; otherwise it will always say "false".
1579  */
1580 bool
1581 is_superuser(void)
1582 {
1583         const char *val;
1584
1585         if (!pset.db)
1586                 return false;
1587
1588         val = PQparameterStatus(pset.db, "is_superuser");
1589
1590         if (val && strcmp(val, "on") == 0)
1591                 return true;
1592
1593         return false;
1594 }
1595
1596
1597 /*
1598  * Test if the current session uses standard string literals.
1599  *
1600  * Note: With a pre-protocol-3.0 connection this will always say "false",
1601  * which should be the right answer.
1602  */
1603 bool
1604 standard_strings(void)
1605 {
1606         const char *val;
1607
1608         if (!pset.db)
1609                 return false;
1610
1611         val = PQparameterStatus(pset.db, "standard_conforming_strings");
1612
1613         if (val && strcmp(val, "on") == 0)
1614                 return true;
1615
1616         return false;
1617 }
1618
1619
1620 /*
1621  * Return the session user of the current connection.
1622  *
1623  * Note: this will correctly detect the session user only with a
1624  * protocol-3.0 or newer backend; otherwise it will return the
1625  * connection user.
1626  */
1627 const char *
1628 session_username(void)
1629 {
1630         const char *val;
1631
1632         if (!pset.db)
1633                 return NULL;
1634
1635         val = PQparameterStatus(pset.db, "session_authorization");
1636         if (val)
1637                 return val;
1638         else
1639                 return PQuser(pset.db);
1640 }
1641
1642
1643 /* expand_tilde
1644  *
1645  * substitute '~' with HOME or '~username' with username's home dir
1646  *
1647  */
1648 void
1649 expand_tilde(char **filename)
1650 {
1651         if (!filename || !(*filename))
1652                 return;
1653
1654         /*
1655          * WIN32 doesn't use tilde expansion for file names. Also, it uses tilde
1656          * for short versions of long file names, though the tilde is usually
1657          * toward the end, not at the beginning.
1658          */
1659 #ifndef WIN32
1660
1661         /* try tilde expansion */
1662         if (**filename == '~')
1663         {
1664                 char       *fn;
1665                 char            oldp,
1666                                    *p;
1667                 struct passwd *pw;
1668                 char            home[MAXPGPATH];
1669
1670                 fn = *filename;
1671                 *home = '\0';
1672
1673                 p = fn + 1;
1674                 while (*p != '/' && *p != '\0')
1675                         p++;
1676
1677                 oldp = *p;
1678                 *p = '\0';
1679
1680                 if (*(fn + 1) == '\0')
1681                         get_home_path(home);    /* ~ or ~/ only */
1682                 else if ((pw = getpwnam(fn + 1)) != NULL)
1683                         strlcpy(home, pw->pw_dir, sizeof(home));        /* ~user */
1684
1685                 *p = oldp;
1686                 if (strlen(home) != 0)
1687                 {
1688                         char       *newfn;
1689
1690                         newfn = pg_malloc(strlen(home) + strlen(p) + 1);
1691                         strcpy(newfn, home);
1692                         strcat(newfn, p);
1693
1694                         free(fn);
1695                         *filename = newfn;
1696                 }
1697         }
1698 #endif
1699
1700         return;
1701 }