Header And Logo

PostgreSQL
| The world's most advanced open source database.

common.c

Go to the documentation of this file.
00001 /*
00002  * psql - the PostgreSQL interactive terminal
00003  *
00004  * Copyright (c) 2000-2013, PostgreSQL Global Development Group
00005  *
00006  * src/bin/psql/common.c
00007  */
00008 #include "postgres_fe.h"
00009 #include "common.h"
00010 
00011 #include <ctype.h>
00012 #include <signal.h>
00013 #ifndef WIN32
00014 #include <unistd.h>             /* for write() */
00015 #else
00016 #include <io.h>                 /* for _write() */
00017 #include <win32.h>
00018 #endif
00019 
00020 #include "portability/instr_time.h"
00021 
00022 #include "settings.h"
00023 #include "command.h"
00024 #include "copy.h"
00025 #include "mbprint.h"
00026 
00027 
00028 
00029 static bool ExecQueryUsingCursor(const char *query, double *elapsed_msec);
00030 static bool command_no_begin(const char *query);
00031 static bool is_select_command(const char *query);
00032 
00033 /*
00034  * setQFout
00035  * -- handler for -o command line option and \o command
00036  *
00037  * Tries to open file fname (or pipe if fname starts with '|')
00038  * and stores the file handle in pset)
00039  * Upon failure, sets stdout and returns false.
00040  */
00041 bool
00042 setQFout(const char *fname)
00043 {
00044     bool        status = true;
00045 
00046     /* Close old file/pipe */
00047     if (pset.queryFout && pset.queryFout != stdout && pset.queryFout != stderr)
00048     {
00049         if (pset.queryFoutPipe)
00050             pclose(pset.queryFout);
00051         else
00052             fclose(pset.queryFout);
00053     }
00054 
00055     /* If no filename, set stdout */
00056     if (!fname || fname[0] == '\0')
00057     {
00058         pset.queryFout = stdout;
00059         pset.queryFoutPipe = false;
00060     }
00061     else if (*fname == '|')
00062     {
00063         pset.queryFout = popen(fname + 1, "w");
00064         pset.queryFoutPipe = true;
00065     }
00066     else
00067     {
00068         pset.queryFout = fopen(fname, "w");
00069         pset.queryFoutPipe = false;
00070     }
00071 
00072     if (!(pset.queryFout))
00073     {
00074         psql_error("%s: %s\n", fname, strerror(errno));
00075         pset.queryFout = stdout;
00076         pset.queryFoutPipe = false;
00077         status = false;
00078     }
00079 
00080     /* Direct signals */
00081 #ifndef WIN32
00082     pqsignal(SIGPIPE, pset.queryFoutPipe ? SIG_IGN : SIG_DFL);
00083 #endif
00084 
00085     return status;
00086 }
00087 
00088 
00089 
00090 /*
00091  * Error reporting for scripts. Errors should look like
00092  *   psql:filename:lineno: message
00093  *
00094  */
00095 void
00096 psql_error(const char *fmt,...)
00097 {
00098     va_list     ap;
00099 
00100     fflush(stdout);
00101     if (pset.queryFout && pset.queryFout != stdout)
00102         fflush(pset.queryFout);
00103 
00104     if (pset.inputfile)
00105         fprintf(stderr, "%s:%s:" UINT64_FORMAT ": ", pset.progname, pset.inputfile, pset.lineno);
00106     va_start(ap, fmt);
00107     vfprintf(stderr, _(fmt), ap);
00108     va_end(ap);
00109 }
00110 
00111 
00112 
00113 /*
00114  * for backend Notice messages (INFO, WARNING, etc)
00115  */
00116 void
00117 NoticeProcessor(void *arg, const char *message)
00118 {
00119     (void) arg;                 /* not used */
00120     psql_error("%s", message);
00121 }
00122 
00123 
00124 
00125 /*
00126  * Code to support query cancellation
00127  *
00128  * Before we start a query, we enable the SIGINT signal catcher to send a
00129  * cancel request to the backend. Note that sending the cancel directly from
00130  * the signal handler is safe because PQcancel() is written to make it
00131  * so. We use write() to report to stderr because it's better to use simple
00132  * facilities in a signal handler.
00133  *
00134  * On win32, the signal canceling happens on a separate thread, because
00135  * that's how SetConsoleCtrlHandler works. The PQcancel function is safe
00136  * for this (unlike PQrequestCancel). However, a CRITICAL_SECTION is required
00137  * to protect the PGcancel structure against being changed while the signal
00138  * thread is using it.
00139  *
00140  * SIGINT is supposed to abort all long-running psql operations, not only
00141  * database queries.  In most places, this is accomplished by checking
00142  * cancel_pressed during long-running loops.  However, that won't work when
00143  * blocked on user input (in readline() or fgets()).  In those places, we
00144  * set sigint_interrupt_enabled TRUE while blocked, instructing the signal
00145  * catcher to longjmp through sigint_interrupt_jmp.  We assume readline and
00146  * fgets are coded to handle possible interruption.  (XXX currently this does
00147  * not work on win32, so control-C is less useful there)
00148  */
00149 volatile bool sigint_interrupt_enabled = false;
00150 
00151 sigjmp_buf  sigint_interrupt_jmp;
00152 
00153 static PGcancel *volatile cancelConn = NULL;
00154 
00155 #ifdef WIN32
00156 static CRITICAL_SECTION cancelConnLock;
00157 #endif
00158 
00159 /* Used from signal handlers, no buffering */
00160 #define write_stderr(str)   write(fileno(stderr), str, strlen(str))
00161 
00162 
00163 #ifndef WIN32
00164 
00165 static void
00166 handle_sigint(SIGNAL_ARGS)
00167 {
00168     int         save_errno = errno;
00169     int         rc;
00170     char        errbuf[256];
00171 
00172     /* if we are waiting for input, longjmp out of it */
00173     if (sigint_interrupt_enabled)
00174     {
00175         sigint_interrupt_enabled = false;
00176         siglongjmp(sigint_interrupt_jmp, 1);
00177     }
00178 
00179     /* else, set cancel flag to stop any long-running loops */
00180     cancel_pressed = true;
00181 
00182     /* and send QueryCancel if we are processing a database query */
00183     if (cancelConn != NULL)
00184     {
00185         if (PQcancel(cancelConn, errbuf, sizeof(errbuf)))
00186         {
00187             rc = write_stderr("Cancel request sent\n");
00188             (void) rc;          /* ignore errors, nothing we can do here */
00189         }
00190         else
00191         {
00192             rc = write_stderr("Could not send cancel request: ");
00193             (void) rc;          /* ignore errors, nothing we can do here */
00194             rc = write_stderr(errbuf);
00195             (void) rc;          /* ignore errors, nothing we can do here */
00196         }
00197     }
00198 
00199     errno = save_errno;         /* just in case the write changed it */
00200 }
00201 
00202 void
00203 setup_cancel_handler(void)
00204 {
00205     pqsignal(SIGINT, handle_sigint);
00206 }
00207 #else                           /* WIN32 */
00208 
00209 static BOOL WINAPI
00210 consoleHandler(DWORD dwCtrlType)
00211 {
00212     char        errbuf[256];
00213 
00214     if (dwCtrlType == CTRL_C_EVENT ||
00215         dwCtrlType == CTRL_BREAK_EVENT)
00216     {
00217         /*
00218          * Can't longjmp here, because we are in wrong thread :-(
00219          */
00220 
00221         /* set cancel flag to stop any long-running loops */
00222         cancel_pressed = true;
00223 
00224         /* and send QueryCancel if we are processing a database query */
00225         EnterCriticalSection(&cancelConnLock);
00226         if (cancelConn != NULL)
00227         {
00228             if (PQcancel(cancelConn, errbuf, sizeof(errbuf)))
00229                 write_stderr("Cancel request sent\n");
00230             else
00231             {
00232                 write_stderr("Could not send cancel request: ");
00233                 write_stderr(errbuf);
00234             }
00235         }
00236         LeaveCriticalSection(&cancelConnLock);
00237 
00238         return TRUE;
00239     }
00240     else
00241         /* Return FALSE for any signals not being handled */
00242         return FALSE;
00243 }
00244 
00245 void
00246 setup_cancel_handler(void)
00247 {
00248     InitializeCriticalSection(&cancelConnLock);
00249 
00250     SetConsoleCtrlHandler(consoleHandler, TRUE);
00251 }
00252 #endif   /* WIN32 */
00253 
00254 
00255 /* ConnectionUp
00256  *
00257  * Returns whether our backend connection is still there.
00258  */
00259 static bool
00260 ConnectionUp(void)
00261 {
00262     return PQstatus(pset.db) != CONNECTION_BAD;
00263 }
00264 
00265 
00266 
00267 /* CheckConnection
00268  *
00269  * Verify that we still have a good connection to the backend, and if not,
00270  * see if it can be restored.
00271  *
00272  * Returns true if either the connection was still there, or it could be
00273  * restored successfully; false otherwise.  If, however, there was no
00274  * connection and the session is non-interactive, this will exit the program
00275  * with a code of EXIT_BADCONN.
00276  */
00277 static bool
00278 CheckConnection(void)
00279 {
00280     bool        OK;
00281 
00282     OK = ConnectionUp();
00283     if (!OK)
00284     {
00285         if (!pset.cur_cmd_interactive)
00286         {
00287             psql_error("connection to server was lost\n");
00288             exit(EXIT_BADCONN);
00289         }
00290 
00291         psql_error("The connection to the server was lost. Attempting reset: ");
00292         PQreset(pset.db);
00293         OK = ConnectionUp();
00294         if (!OK)
00295         {
00296             psql_error("Failed.\n");
00297             PQfinish(pset.db);
00298             pset.db = NULL;
00299             ResetCancelConn();
00300             UnsyncVariables();
00301         }
00302         else
00303             psql_error("Succeeded.\n");
00304     }
00305 
00306     return OK;
00307 }
00308 
00309 
00310 
00311 /*
00312  * SetCancelConn
00313  *
00314  * Set cancelConn to point to the current database connection.
00315  */
00316 void
00317 SetCancelConn(void)
00318 {
00319     PGcancel   *oldCancelConn;
00320 
00321 #ifdef WIN32
00322     EnterCriticalSection(&cancelConnLock);
00323 #endif
00324 
00325     /* Free the old one if we have one */
00326     oldCancelConn = cancelConn;
00327     /* be sure handle_sigint doesn't use pointer while freeing */
00328     cancelConn = NULL;
00329 
00330     if (oldCancelConn != NULL)
00331         PQfreeCancel(oldCancelConn);
00332 
00333     cancelConn = PQgetCancel(pset.db);
00334 
00335 #ifdef WIN32
00336     LeaveCriticalSection(&cancelConnLock);
00337 #endif
00338 }
00339 
00340 
00341 /*
00342  * ResetCancelConn
00343  *
00344  * Free the current cancel connection, if any, and set to NULL.
00345  */
00346 void
00347 ResetCancelConn(void)
00348 {
00349     PGcancel   *oldCancelConn;
00350 
00351 #ifdef WIN32
00352     EnterCriticalSection(&cancelConnLock);
00353 #endif
00354 
00355     oldCancelConn = cancelConn;
00356     /* be sure handle_sigint doesn't use pointer while freeing */
00357     cancelConn = NULL;
00358 
00359     if (oldCancelConn != NULL)
00360         PQfreeCancel(oldCancelConn);
00361 
00362 #ifdef WIN32
00363     LeaveCriticalSection(&cancelConnLock);
00364 #endif
00365 }
00366 
00367 
00368 /*
00369  * AcceptResult
00370  *
00371  * Checks whether a result is valid, giving an error message if necessary;
00372  * and ensures that the connection to the backend is still up.
00373  *
00374  * Returns true for valid result, false for error state.
00375  */
00376 static bool
00377 AcceptResult(const PGresult *result)
00378 {
00379     bool        OK;
00380 
00381     if (!result)
00382         OK = false;
00383     else
00384         switch (PQresultStatus(result))
00385         {
00386             case PGRES_COMMAND_OK:
00387             case PGRES_TUPLES_OK:
00388             case PGRES_EMPTY_QUERY:
00389             case PGRES_COPY_IN:
00390             case PGRES_COPY_OUT:
00391                 /* Fine, do nothing */
00392                 OK = true;
00393                 break;
00394 
00395             case PGRES_BAD_RESPONSE:
00396             case PGRES_NONFATAL_ERROR:
00397             case PGRES_FATAL_ERROR:
00398                 OK = false;
00399                 break;
00400 
00401             default:
00402                 OK = false;
00403                 psql_error("unexpected PQresultStatus: %d\n",
00404                            PQresultStatus(result));
00405                 break;
00406         }
00407 
00408     if (!OK)
00409     {
00410         const char *error = PQerrorMessage(pset.db);
00411 
00412         if (strlen(error))
00413             psql_error("%s", error);
00414 
00415         CheckConnection();
00416     }
00417 
00418     return OK;
00419 }
00420 
00421 
00422 
00423 /*
00424  * PSQLexec
00425  *
00426  * This is the way to send "backdoor" queries (those not directly entered
00427  * by the user). It is subject to -E but not -e.
00428  *
00429  * In autocommit-off mode, a new transaction block is started if start_xact
00430  * is true; nothing special is done when start_xact is false.  Typically,
00431  * start_xact = false is used for SELECTs and explicit BEGIN/COMMIT commands.
00432  *
00433  * Caller is responsible for handling the ensuing processing if a COPY
00434  * command is sent.
00435  *
00436  * Note: we don't bother to check PQclientEncoding; it is assumed that no
00437  * caller uses this path to issue "SET CLIENT_ENCODING".
00438  */
00439 PGresult *
00440 PSQLexec(const char *query, bool start_xact)
00441 {
00442     PGresult   *res;
00443 
00444     if (!pset.db)
00445     {
00446         psql_error("You are currently not connected to a database.\n");
00447         return NULL;
00448     }
00449 
00450     if (pset.echo_hidden != PSQL_ECHO_HIDDEN_OFF)
00451     {
00452         printf(_("********* QUERY **********\n"
00453                  "%s\n"
00454                  "**************************\n\n"), query);
00455         fflush(stdout);
00456         if (pset.logfile)
00457         {
00458             fprintf(pset.logfile,
00459                     _("********* QUERY **********\n"
00460                       "%s\n"
00461                       "**************************\n\n"), query);
00462             fflush(pset.logfile);
00463         }
00464 
00465         if (pset.echo_hidden == PSQL_ECHO_HIDDEN_NOEXEC)
00466             return NULL;
00467     }
00468 
00469     SetCancelConn();
00470 
00471     if (start_xact &&
00472         !pset.autocommit &&
00473         PQtransactionStatus(pset.db) == PQTRANS_IDLE)
00474     {
00475         res = PQexec(pset.db, "BEGIN");
00476         if (PQresultStatus(res) != PGRES_COMMAND_OK)
00477         {
00478             psql_error("%s", PQerrorMessage(pset.db));
00479             PQclear(res);
00480             ResetCancelConn();
00481             return NULL;
00482         }
00483         PQclear(res);
00484     }
00485 
00486     res = PQexec(pset.db, query);
00487 
00488     ResetCancelConn();
00489 
00490     if (!AcceptResult(res))
00491     {
00492         PQclear(res);
00493         res = NULL;
00494     }
00495 
00496     return res;
00497 }
00498 
00499 
00500 
00501 /*
00502  * PrintNotifications: check for asynchronous notifications, and print them out
00503  */
00504 static void
00505 PrintNotifications(void)
00506 {
00507     PGnotify   *notify;
00508 
00509     while ((notify = PQnotifies(pset.db)))
00510     {
00511         /* for backward compatibility, only show payload if nonempty */
00512         if (notify->extra[0])
00513             fprintf(pset.queryFout, _("Asynchronous notification \"%s\" with payload \"%s\" received from server process with PID %d.\n"),
00514                     notify->relname, notify->extra, notify->be_pid);
00515         else
00516             fprintf(pset.queryFout, _("Asynchronous notification \"%s\" received from server process with PID %d.\n"),
00517                     notify->relname, notify->be_pid);
00518         fflush(pset.queryFout);
00519         PQfreemem(notify);
00520     }
00521 }
00522 
00523 
00524 /*
00525  * PrintQueryTuples: assuming query result is OK, print its tuples
00526  *
00527  * Returns true if successful, false otherwise.
00528  */
00529 static bool
00530 PrintQueryTuples(const PGresult *results)
00531 {
00532     printQueryOpt my_popt = pset.popt;
00533 
00534     /* write output to \g argument, if any */
00535     if (pset.gfname)
00536     {
00537         /* keep this code in sync with ExecQueryUsingCursor */
00538         FILE       *queryFout_copy = pset.queryFout;
00539         bool        queryFoutPipe_copy = pset.queryFoutPipe;
00540 
00541         pset.queryFout = stdout;    /* so it doesn't get closed */
00542 
00543         /* open file/pipe */
00544         if (!setQFout(pset.gfname))
00545         {
00546             pset.queryFout = queryFout_copy;
00547             pset.queryFoutPipe = queryFoutPipe_copy;
00548             return false;
00549         }
00550 
00551         printQuery(results, &my_popt, pset.queryFout, pset.logfile);
00552 
00553         /* close file/pipe, restore old setting */
00554         setQFout(NULL);
00555 
00556         pset.queryFout = queryFout_copy;
00557         pset.queryFoutPipe = queryFoutPipe_copy;
00558     }
00559     else
00560         printQuery(results, &my_popt, pset.queryFout, pset.logfile);
00561 
00562     return true;
00563 }
00564 
00565 
00566 /*
00567  * StoreQueryTuple: assuming query result is OK, save data into variables
00568  *
00569  * Returns true if successful, false otherwise.
00570  */
00571 static bool
00572 StoreQueryTuple(const PGresult *result)
00573 {
00574     bool        success = true;
00575 
00576     if (PQntuples(result) < 1)
00577     {
00578         psql_error("no rows returned for \\gset\n");
00579         success = false;
00580     }
00581     else if (PQntuples(result) > 1)
00582     {
00583         psql_error("more than one row returned for \\gset\n");
00584         success = false;
00585     }
00586     else
00587     {
00588         int         i;
00589 
00590         for (i = 0; i < PQnfields(result); i++)
00591         {
00592             char       *colname = PQfname(result, i);
00593             char       *varname;
00594             char       *value;
00595 
00596             /* concate prefix and column name */
00597             varname = pg_malloc(strlen(pset.gset_prefix) + strlen(colname) + 1);
00598             strcpy(varname, pset.gset_prefix);
00599             strcat(varname, colname);
00600 
00601             if (!PQgetisnull(result, 0, i))
00602                 value = PQgetvalue(result, 0, i);
00603             else
00604             {
00605                 /* for NULL value, unset rather than set the variable */
00606                 value = NULL;
00607             }
00608 
00609             if (!SetVariable(pset.vars, varname, value))
00610             {
00611                 psql_error("could not set variable \"%s\"\n", varname);
00612                 free(varname);
00613                 success = false;
00614                 break;
00615             }
00616 
00617             free(varname);
00618         }
00619     }
00620 
00621     return success;
00622 }
00623 
00624 
00625 /*
00626  * ProcessResult: utility function for use by SendQuery() only
00627  *
00628  * When our command string contained a COPY FROM STDIN or COPY TO STDOUT,
00629  * PQexec() has stopped at the PGresult associated with the first such
00630  * command.  In that event, we'll marshal data for the COPY and then cycle
00631  * through any subsequent PGresult objects.
00632  *
00633  * When the command string contained no affected COPY command, this function
00634  * degenerates to an AcceptResult() call.
00635  *
00636  * Changes its argument to point to the last PGresult of the command string,
00637  * or NULL if that result was for a COPY FROM STDIN or COPY TO STDOUT.
00638  *
00639  * Returns true on complete success, false otherwise.  Possible failure modes
00640  * include purely client-side problems; check the transaction status for the
00641  * server-side opinion.
00642  */
00643 static bool
00644 ProcessResult(PGresult **results)
00645 {
00646     PGresult   *next_result;
00647     bool        success = true;
00648     bool        first_cycle = true;
00649 
00650     do
00651     {
00652         ExecStatusType result_status;
00653         bool        is_copy;
00654 
00655         if (!AcceptResult(*results))
00656         {
00657             /*
00658              * Failure at this point is always a server-side failure or a
00659              * failure to submit the command string.  Either way, we're
00660              * finished with this command string.
00661              */
00662             success = false;
00663             break;
00664         }
00665 
00666         result_status = PQresultStatus(*results);
00667         switch (result_status)
00668         {
00669             case PGRES_EMPTY_QUERY:
00670             case PGRES_COMMAND_OK:
00671             case PGRES_TUPLES_OK:
00672                 is_copy = false;
00673                 break;
00674 
00675             case PGRES_COPY_OUT:
00676             case PGRES_COPY_IN:
00677                 is_copy = true;
00678                 break;
00679 
00680             default:
00681                 /* AcceptResult() should have caught anything else. */
00682                 is_copy = false;
00683                 psql_error("unexpected PQresultStatus: %d\n", result_status);
00684                 break;
00685         }
00686 
00687         if (is_copy)
00688         {
00689             /*
00690              * Marshal the COPY data.  Either subroutine will get the
00691              * connection out of its COPY state, then call PQresultStatus()
00692              * once and report any error.
00693              */
00694             SetCancelConn();
00695             if (result_status == PGRES_COPY_OUT)
00696                 success = handleCopyOut(pset.db, pset.queryFout) && success;
00697             else
00698                 success = handleCopyIn(pset.db, pset.cur_cmd_source,
00699                                        PQbinaryTuples(*results)) && success;
00700             ResetCancelConn();
00701 
00702             /*
00703              * Call PQgetResult() once more.  In the typical case of a
00704              * single-command string, it will return NULL.  Otherwise, we'll
00705              * have other results to process that may include other COPYs.
00706              */
00707             PQclear(*results);
00708             *results = next_result = PQgetResult(pset.db);
00709         }
00710         else if (first_cycle)
00711             /* fast path: no COPY commands; PQexec visited all results */
00712             break;
00713         else if ((next_result = PQgetResult(pset.db)))
00714         {
00715             /* non-COPY command(s) after a COPY: keep the last one */
00716             PQclear(*results);
00717             *results = next_result;
00718         }
00719 
00720         first_cycle = false;
00721     } while (next_result);
00722 
00723     /* may need this to recover from conn loss during COPY */
00724     if (!first_cycle && !CheckConnection())
00725         return false;
00726 
00727     return success;
00728 }
00729 
00730 
00731 /*
00732  * PrintQueryStatus: report command status as required
00733  *
00734  * Note: Utility function for use by PrintQueryResults() only.
00735  */
00736 static void
00737 PrintQueryStatus(PGresult *results)
00738 {
00739     char        buf[16];
00740 
00741     if (!pset.quiet)
00742     {
00743         if (pset.popt.topt.format == PRINT_HTML)
00744         {
00745             fputs("<p>", pset.queryFout);
00746             html_escaped_print(PQcmdStatus(results), pset.queryFout);
00747             fputs("</p>\n", pset.queryFout);
00748         }
00749         else
00750             fprintf(pset.queryFout, "%s\n", PQcmdStatus(results));
00751     }
00752 
00753     if (pset.logfile)
00754         fprintf(pset.logfile, "%s\n", PQcmdStatus(results));
00755 
00756     snprintf(buf, sizeof(buf), "%u", (unsigned int) PQoidValue(results));
00757     SetVariable(pset.vars, "LASTOID", buf);
00758 }
00759 
00760 
00761 /*
00762  * PrintQueryResults: print out (or store) query results as required
00763  *
00764  * Note: Utility function for use by SendQuery() only.
00765  *
00766  * Returns true if the query executed successfully, false otherwise.
00767  */
00768 static bool
00769 PrintQueryResults(PGresult *results)
00770 {
00771     bool        success;
00772     const char *cmdstatus;
00773 
00774     if (!results)
00775         return false;
00776 
00777     switch (PQresultStatus(results))
00778     {
00779         case PGRES_TUPLES_OK:
00780             /* store or print the data ... */
00781             if (pset.gset_prefix)
00782                 success = StoreQueryTuple(results);
00783             else
00784                 success = PrintQueryTuples(results);
00785             /* if it's INSERT/UPDATE/DELETE RETURNING, also print status */
00786             cmdstatus = PQcmdStatus(results);
00787             if (strncmp(cmdstatus, "INSERT", 6) == 0 ||
00788                 strncmp(cmdstatus, "UPDATE", 6) == 0 ||
00789                 strncmp(cmdstatus, "DELETE", 6) == 0)
00790                 PrintQueryStatus(results);
00791             break;
00792 
00793         case PGRES_COMMAND_OK:
00794             PrintQueryStatus(results);
00795             success = true;
00796             break;
00797 
00798         case PGRES_EMPTY_QUERY:
00799             success = true;
00800             break;
00801 
00802         case PGRES_COPY_OUT:
00803         case PGRES_COPY_IN:
00804             /* nothing to do here */
00805             success = true;
00806             break;
00807 
00808         case PGRES_BAD_RESPONSE:
00809         case PGRES_NONFATAL_ERROR:
00810         case PGRES_FATAL_ERROR:
00811             success = false;
00812             break;
00813 
00814         default:
00815             success = false;
00816             psql_error("unexpected PQresultStatus: %d\n",
00817                        PQresultStatus(results));
00818             break;
00819     }
00820 
00821     fflush(pset.queryFout);
00822 
00823     return success;
00824 }
00825 
00826 
00827 /*
00828  * SendQuery: send the query string to the backend
00829  * (and print out results)
00830  *
00831  * Note: This is the "front door" way to send a query. That is, use it to
00832  * send queries actually entered by the user. These queries will be subject to
00833  * single step mode.
00834  * To send "back door" queries (generated by slash commands, etc.) in a
00835  * controlled way, use PSQLexec().
00836  *
00837  * Returns true if the query executed successfully, false otherwise.
00838  */
00839 bool
00840 SendQuery(const char *query)
00841 {
00842     PGresult   *results;
00843     PGTransactionStatusType transaction_status;
00844     double      elapsed_msec = 0;
00845     bool        OK = false;
00846     bool        on_error_rollback_savepoint = false;
00847     static bool on_error_rollback_warning = false;
00848 
00849     if (!pset.db)
00850     {
00851         psql_error("You are currently not connected to a database.\n");
00852         goto sendquery_cleanup;
00853     }
00854 
00855     if (pset.singlestep)
00856     {
00857         char        buf[3];
00858 
00859         printf(_("***(Single step mode: verify command)*******************************************\n"
00860                  "%s\n"
00861                  "***(press return to proceed or enter x and return to cancel)********************\n"),
00862                query);
00863         fflush(stdout);
00864         if (fgets(buf, sizeof(buf), stdin) != NULL)
00865             if (buf[0] == 'x')
00866                 goto sendquery_cleanup;
00867     }
00868     else if (pset.echo == PSQL_ECHO_QUERIES)
00869     {
00870         puts(query);
00871         fflush(stdout);
00872     }
00873 
00874     if (pset.logfile)
00875     {
00876         fprintf(pset.logfile,
00877                 _("********* QUERY **********\n"
00878                   "%s\n"
00879                   "**************************\n\n"), query);
00880         fflush(pset.logfile);
00881     }
00882 
00883     SetCancelConn();
00884 
00885     transaction_status = PQtransactionStatus(pset.db);
00886 
00887     if (transaction_status == PQTRANS_IDLE &&
00888         !pset.autocommit &&
00889         !command_no_begin(query))
00890     {
00891         results = PQexec(pset.db, "BEGIN");
00892         if (PQresultStatus(results) != PGRES_COMMAND_OK)
00893         {
00894             psql_error("%s", PQerrorMessage(pset.db));
00895             PQclear(results);
00896             ResetCancelConn();
00897             goto sendquery_cleanup;
00898         }
00899         PQclear(results);
00900         transaction_status = PQtransactionStatus(pset.db);
00901     }
00902 
00903     if (transaction_status == PQTRANS_INTRANS &&
00904         pset.on_error_rollback != PSQL_ERROR_ROLLBACK_OFF &&
00905         (pset.cur_cmd_interactive ||
00906          pset.on_error_rollback == PSQL_ERROR_ROLLBACK_ON))
00907     {
00908         if (on_error_rollback_warning == false && pset.sversion < 80000)
00909         {
00910             psql_error("The server (version %d.%d) does not support savepoints for ON_ERROR_ROLLBACK.\n",
00911                        pset.sversion / 10000, (pset.sversion / 100) % 100);
00912             on_error_rollback_warning = true;
00913         }
00914         else
00915         {
00916             results = PQexec(pset.db, "SAVEPOINT pg_psql_temporary_savepoint");
00917             if (PQresultStatus(results) != PGRES_COMMAND_OK)
00918             {
00919                 psql_error("%s", PQerrorMessage(pset.db));
00920                 PQclear(results);
00921                 ResetCancelConn();
00922                 goto sendquery_cleanup;
00923             }
00924             PQclear(results);
00925             on_error_rollback_savepoint = true;
00926         }
00927     }
00928 
00929     if (pset.fetch_count <= 0 || !is_select_command(query))
00930     {
00931         /* Default fetch-it-all-and-print mode */
00932         instr_time  before,
00933                     after;
00934 
00935         if (pset.timing)
00936             INSTR_TIME_SET_CURRENT(before);
00937 
00938         results = PQexec(pset.db, query);
00939 
00940         /* these operations are included in the timing result: */
00941         ResetCancelConn();
00942         OK = ProcessResult(&results);
00943 
00944         if (pset.timing)
00945         {
00946             INSTR_TIME_SET_CURRENT(after);
00947             INSTR_TIME_SUBTRACT(after, before);
00948             elapsed_msec = INSTR_TIME_GET_MILLISEC(after);
00949         }
00950 
00951         /* but printing results isn't: */
00952         if (OK && results)
00953             OK = PrintQueryResults(results);
00954     }
00955     else
00956     {
00957         /* Fetch-in-segments mode */
00958         OK = ExecQueryUsingCursor(query, &elapsed_msec);
00959         ResetCancelConn();
00960         results = NULL;         /* PQclear(NULL) does nothing */
00961     }
00962 
00963     /* If we made a temporary savepoint, possibly release/rollback */
00964     if (on_error_rollback_savepoint)
00965     {
00966         const char *svptcmd = NULL;
00967 
00968         transaction_status = PQtransactionStatus(pset.db);
00969 
00970         switch (transaction_status)
00971         {
00972             case PQTRANS_INERROR:
00973                 /* We always rollback on an error */
00974                 svptcmd = "ROLLBACK TO pg_psql_temporary_savepoint";
00975                 break;
00976 
00977             case PQTRANS_IDLE:
00978                 /* If they are no longer in a transaction, then do nothing */
00979                 break;
00980 
00981             case PQTRANS_INTRANS:
00982 
00983                 /*
00984                  * Do nothing if they are messing with savepoints themselves:
00985                  * If the user did RELEASE or ROLLBACK, our savepoint is gone.
00986                  * If they issued a SAVEPOINT, releasing ours would remove
00987                  * theirs.
00988                  */
00989                 if (results &&
00990                     (strcmp(PQcmdStatus(results), "SAVEPOINT") == 0 ||
00991                      strcmp(PQcmdStatus(results), "RELEASE") == 0 ||
00992                      strcmp(PQcmdStatus(results), "ROLLBACK") == 0))
00993                     svptcmd = NULL;
00994                 else
00995                     svptcmd = "RELEASE pg_psql_temporary_savepoint";
00996                 break;
00997 
00998             case PQTRANS_ACTIVE:
00999             case PQTRANS_UNKNOWN:
01000             default:
01001                 OK = false;
01002                 /* PQTRANS_UNKNOWN is expected given a broken connection. */
01003                 if (transaction_status != PQTRANS_UNKNOWN || ConnectionUp())
01004                     psql_error("unexpected transaction status (%d)\n",
01005                                transaction_status);
01006                 break;
01007         }
01008 
01009         if (svptcmd)
01010         {
01011             PGresult   *svptres;
01012 
01013             svptres = PQexec(pset.db, svptcmd);
01014             if (PQresultStatus(svptres) != PGRES_COMMAND_OK)
01015             {
01016                 psql_error("%s", PQerrorMessage(pset.db));
01017                 PQclear(svptres);
01018                 OK = false;
01019 
01020                 PQclear(results);
01021                 ResetCancelConn();
01022                 goto sendquery_cleanup;
01023             }
01024             PQclear(svptres);
01025         }
01026     }
01027 
01028     PQclear(results);
01029 
01030     /* Possible microtiming output */
01031     if (pset.timing)
01032         printf(_("Time: %.3f ms\n"), elapsed_msec);
01033 
01034     /* check for events that may occur during query execution */
01035 
01036     if (pset.encoding != PQclientEncoding(pset.db) &&
01037         PQclientEncoding(pset.db) >= 0)
01038     {
01039         /* track effects of SET CLIENT_ENCODING */
01040         pset.encoding = PQclientEncoding(pset.db);
01041         pset.popt.topt.encoding = pset.encoding;
01042         SetVariable(pset.vars, "ENCODING",
01043                     pg_encoding_to_char(pset.encoding));
01044     }
01045 
01046     PrintNotifications();
01047 
01048     /* perform cleanup that should occur after any attempted query */
01049 
01050 sendquery_cleanup:
01051 
01052     /* reset \g's output-to-filename trigger */
01053     if (pset.gfname)
01054     {
01055         free(pset.gfname);
01056         pset.gfname = NULL;
01057     }
01058 
01059     /* reset \gset trigger */
01060     if (pset.gset_prefix)
01061     {
01062         free(pset.gset_prefix);
01063         pset.gset_prefix = NULL;
01064     }
01065 
01066     return OK;
01067 }
01068 
01069 
01070 /*
01071  * ExecQueryUsingCursor: run a SELECT-like query using a cursor
01072  *
01073  * This feature allows result sets larger than RAM to be dealt with.
01074  *
01075  * Returns true if the query executed successfully, false otherwise.
01076  *
01077  * If pset.timing is on, total query time (exclusive of result-printing) is
01078  * stored into *elapsed_msec.
01079  */
01080 static bool
01081 ExecQueryUsingCursor(const char *query, double *elapsed_msec)
01082 {
01083     bool        OK = true;
01084     PGresult   *results;
01085     PQExpBufferData buf;
01086     printQueryOpt my_popt = pset.popt;
01087     FILE       *queryFout_copy = pset.queryFout;
01088     bool        queryFoutPipe_copy = pset.queryFoutPipe;
01089     bool        started_txn = false;
01090     bool        did_pager = false;
01091     int         ntuples;
01092     int         fetch_count;
01093     char        fetch_cmd[64];
01094     instr_time  before,
01095                 after;
01096     int         flush_error;
01097 
01098     *elapsed_msec = 0;
01099 
01100     /* initialize print options for partial table output */
01101     my_popt.topt.start_table = true;
01102     my_popt.topt.stop_table = false;
01103     my_popt.topt.prior_records = 0;
01104 
01105     if (pset.timing)
01106         INSTR_TIME_SET_CURRENT(before);
01107 
01108     /* if we're not in a transaction, start one */
01109     if (PQtransactionStatus(pset.db) == PQTRANS_IDLE)
01110     {
01111         results = PQexec(pset.db, "BEGIN");
01112         OK = AcceptResult(results) &&
01113             (PQresultStatus(results) == PGRES_COMMAND_OK);
01114         PQclear(results);
01115         if (!OK)
01116             return false;
01117         started_txn = true;
01118     }
01119 
01120     /* Send DECLARE CURSOR */
01121     initPQExpBuffer(&buf);
01122     appendPQExpBuffer(&buf, "DECLARE _psql_cursor NO SCROLL CURSOR FOR\n%s",
01123                       query);
01124 
01125     results = PQexec(pset.db, buf.data);
01126     OK = AcceptResult(results) &&
01127         (PQresultStatus(results) == PGRES_COMMAND_OK);
01128     PQclear(results);
01129     termPQExpBuffer(&buf);
01130     if (!OK)
01131         goto cleanup;
01132 
01133     if (pset.timing)
01134     {
01135         INSTR_TIME_SET_CURRENT(after);
01136         INSTR_TIME_SUBTRACT(after, before);
01137         *elapsed_msec += INSTR_TIME_GET_MILLISEC(after);
01138     }
01139 
01140     /*
01141      * In \gset mode, we force the fetch count to be 2, so that we will throw
01142      * the appropriate error if the query returns more than one row.
01143      */
01144     if (pset.gset_prefix)
01145         fetch_count = 2;
01146     else
01147         fetch_count = pset.fetch_count;
01148 
01149     snprintf(fetch_cmd, sizeof(fetch_cmd),
01150              "FETCH FORWARD %d FROM _psql_cursor",
01151              fetch_count);
01152 
01153     /* prepare to write output to \g argument, if any */
01154     if (pset.gfname)
01155     {
01156         /* keep this code in sync with PrintQueryTuples */
01157         pset.queryFout = stdout;    /* so it doesn't get closed */
01158 
01159         /* open file/pipe */
01160         if (!setQFout(pset.gfname))
01161         {
01162             pset.queryFout = queryFout_copy;
01163             pset.queryFoutPipe = queryFoutPipe_copy;
01164             OK = false;
01165             goto cleanup;
01166         }
01167     }
01168 
01169     /* clear any pre-existing error indication on the output stream */
01170     clearerr(pset.queryFout);
01171 
01172     for (;;)
01173     {
01174         if (pset.timing)
01175             INSTR_TIME_SET_CURRENT(before);
01176 
01177         /* get fetch_count tuples at a time */
01178         results = PQexec(pset.db, fetch_cmd);
01179 
01180         if (pset.timing)
01181         {
01182             INSTR_TIME_SET_CURRENT(after);
01183             INSTR_TIME_SUBTRACT(after, before);
01184             *elapsed_msec += INSTR_TIME_GET_MILLISEC(after);
01185         }
01186 
01187         if (PQresultStatus(results) != PGRES_TUPLES_OK)
01188         {
01189             /* shut down pager before printing error message */
01190             if (did_pager)
01191             {
01192                 ClosePager(pset.queryFout);
01193                 pset.queryFout = queryFout_copy;
01194                 pset.queryFoutPipe = queryFoutPipe_copy;
01195                 did_pager = false;
01196             }
01197 
01198             OK = AcceptResult(results);
01199             Assert(!OK);
01200             PQclear(results);
01201             break;
01202         }
01203 
01204         if (pset.gset_prefix)
01205         {
01206             /* StoreQueryTuple will complain if not exactly one row */
01207             OK = StoreQueryTuple(results);
01208             PQclear(results);
01209             break;
01210         }
01211 
01212         ntuples = PQntuples(results);
01213 
01214         if (ntuples < fetch_count)
01215         {
01216             /* this is the last result set, so allow footer decoration */
01217             my_popt.topt.stop_table = true;
01218         }
01219         else if (pset.queryFout == stdout && !did_pager)
01220         {
01221             /*
01222              * If query requires multiple result sets, hack to ensure that
01223              * only one pager instance is used for the whole mess
01224              */
01225             pset.queryFout = PageOutput(100000, my_popt.topt.pager);
01226             did_pager = true;
01227         }
01228 
01229         printQuery(results, &my_popt, pset.queryFout, pset.logfile);
01230 
01231         PQclear(results);
01232 
01233         /* after the first result set, disallow header decoration */
01234         my_popt.topt.start_table = false;
01235         my_popt.topt.prior_records += ntuples;
01236 
01237         /*
01238          * Make sure to flush the output stream, so intermediate results are
01239          * visible to the client immediately.  We check the results because if
01240          * the pager dies/exits/etc, there's no sense throwing more data at
01241          * it.
01242          */
01243         flush_error = fflush(pset.queryFout);
01244 
01245         /*
01246          * Check if we are at the end, if a cancel was pressed, or if there
01247          * were any errors either trying to flush out the results, or more
01248          * generally on the output stream at all.  If we hit any errors
01249          * writing things to the stream, we presume $PAGER has disappeared and
01250          * stop bothering to pull down more data.
01251          */
01252         if (ntuples < fetch_count || cancel_pressed || flush_error ||
01253             ferror(pset.queryFout))
01254             break;
01255     }
01256 
01257     /* close \g argument file/pipe, restore old setting */
01258     if (pset.gfname)
01259     {
01260         /* keep this code in sync with PrintQueryTuples */
01261         setQFout(NULL);
01262 
01263         pset.queryFout = queryFout_copy;
01264         pset.queryFoutPipe = queryFoutPipe_copy;
01265     }
01266     else if (did_pager)
01267     {
01268         ClosePager(pset.queryFout);
01269         pset.queryFout = queryFout_copy;
01270         pset.queryFoutPipe = queryFoutPipe_copy;
01271     }
01272 
01273 cleanup:
01274     if (pset.timing)
01275         INSTR_TIME_SET_CURRENT(before);
01276 
01277     /*
01278      * We try to close the cursor on either success or failure, but on failure
01279      * ignore the result (it's probably just a bleat about being in an aborted
01280      * transaction)
01281      */
01282     results = PQexec(pset.db, "CLOSE _psql_cursor");
01283     if (OK)
01284     {
01285         OK = AcceptResult(results) &&
01286             (PQresultStatus(results) == PGRES_COMMAND_OK);
01287     }
01288     PQclear(results);
01289 
01290     if (started_txn)
01291     {
01292         results = PQexec(pset.db, OK ? "COMMIT" : "ROLLBACK");
01293         OK &= AcceptResult(results) &&
01294             (PQresultStatus(results) == PGRES_COMMAND_OK);
01295         PQclear(results);
01296     }
01297 
01298     if (pset.timing)
01299     {
01300         INSTR_TIME_SET_CURRENT(after);
01301         INSTR_TIME_SUBTRACT(after, before);
01302         *elapsed_msec += INSTR_TIME_GET_MILLISEC(after);
01303     }
01304 
01305     return OK;
01306 }
01307 
01308 
01309 /*
01310  * Advance the given char pointer over white space and SQL comments.
01311  */
01312 static const char *
01313 skip_white_space(const char *query)
01314 {
01315     int         cnestlevel = 0; /* slash-star comment nest level */
01316 
01317     while (*query)
01318     {
01319         int         mblen = PQmblen(query, pset.encoding);
01320 
01321         /*
01322          * Note: we assume the encoding is a superset of ASCII, so that for
01323          * example "query[0] == '/'" is meaningful.  However, we do NOT assume
01324          * that the second and subsequent bytes of a multibyte character
01325          * couldn't look like ASCII characters; so it is critical to advance
01326          * by mblen, not 1, whenever we haven't exactly identified the
01327          * character we are skipping over.
01328          */
01329         if (isspace((unsigned char) *query))
01330             query += mblen;
01331         else if (query[0] == '/' && query[1] == '*')
01332         {
01333             cnestlevel++;
01334             query += 2;
01335         }
01336         else if (cnestlevel > 0 && query[0] == '*' && query[1] == '/')
01337         {
01338             cnestlevel--;
01339             query += 2;
01340         }
01341         else if (cnestlevel == 0 && query[0] == '-' && query[1] == '-')
01342         {
01343             query += 2;
01344 
01345             /*
01346              * We have to skip to end of line since any slash-star inside the
01347              * -- comment does NOT start a slash-star comment.
01348              */
01349             while (*query)
01350             {
01351                 if (*query == '\n')
01352                 {
01353                     query++;
01354                     break;
01355                 }
01356                 query += PQmblen(query, pset.encoding);
01357             }
01358         }
01359         else if (cnestlevel > 0)
01360             query += mblen;
01361         else
01362             break;              /* found first token */
01363     }
01364 
01365     return query;
01366 }
01367 
01368 
01369 /*
01370  * Check whether a command is one of those for which we should NOT start
01371  * a new transaction block (ie, send a preceding BEGIN).
01372  *
01373  * These include the transaction control statements themselves, plus
01374  * certain statements that the backend disallows inside transaction blocks.
01375  */
01376 static bool
01377 command_no_begin(const char *query)
01378 {
01379     int         wordlen;
01380 
01381     /*
01382      * First we must advance over any whitespace and comments.
01383      */
01384     query = skip_white_space(query);
01385 
01386     /*
01387      * Check word length (since "beginx" is not "begin").
01388      */
01389     wordlen = 0;
01390     while (isalpha((unsigned char) query[wordlen]))
01391         wordlen += PQmblen(&query[wordlen], pset.encoding);
01392 
01393     /*
01394      * Transaction control commands.  These should include every keyword that
01395      * gives rise to a TransactionStmt in the backend grammar, except for the
01396      * savepoint-related commands.
01397      *
01398      * (We assume that START must be START TRANSACTION, since there is
01399      * presently no other "START foo" command.)
01400      */
01401     if (wordlen == 5 && pg_strncasecmp(query, "abort", 5) == 0)
01402         return true;
01403     if (wordlen == 5 && pg_strncasecmp(query, "begin", 5) == 0)
01404         return true;
01405     if (wordlen == 5 && pg_strncasecmp(query, "start", 5) == 0)
01406         return true;
01407     if (wordlen == 6 && pg_strncasecmp(query, "commit", 6) == 0)
01408         return true;
01409     if (wordlen == 3 && pg_strncasecmp(query, "end", 3) == 0)
01410         return true;
01411     if (wordlen == 8 && pg_strncasecmp(query, "rollback", 8) == 0)
01412         return true;
01413     if (wordlen == 7 && pg_strncasecmp(query, "prepare", 7) == 0)
01414     {
01415         /* PREPARE TRANSACTION is a TC command, PREPARE foo is not */
01416         query += wordlen;
01417 
01418         query = skip_white_space(query);
01419 
01420         wordlen = 0;
01421         while (isalpha((unsigned char) query[wordlen]))
01422             wordlen += PQmblen(&query[wordlen], pset.encoding);
01423 
01424         if (wordlen == 11 && pg_strncasecmp(query, "transaction", 11) == 0)
01425             return true;
01426         return false;
01427     }
01428 
01429     /*
01430      * Commands not allowed within transactions.  The statements checked for
01431      * here should be exactly those that call PreventTransactionChain() in the
01432      * backend.
01433      */
01434     if (wordlen == 6 && pg_strncasecmp(query, "vacuum", 6) == 0)
01435         return true;
01436     if (wordlen == 7 && pg_strncasecmp(query, "cluster", 7) == 0)
01437     {
01438         /* CLUSTER with any arguments is allowed in transactions */
01439         query += wordlen;
01440 
01441         query = skip_white_space(query);
01442 
01443         if (isalpha((unsigned char) query[0]))
01444             return false;       /* has additional words */
01445         return true;            /* it's CLUSTER without arguments */
01446     }
01447 
01448     if (wordlen == 6 && pg_strncasecmp(query, "create", 6) == 0)
01449     {
01450         query += wordlen;
01451 
01452         query = skip_white_space(query);
01453 
01454         wordlen = 0;
01455         while (isalpha((unsigned char) query[wordlen]))
01456             wordlen += PQmblen(&query[wordlen], pset.encoding);
01457 
01458         if (wordlen == 8 && pg_strncasecmp(query, "database", 8) == 0)
01459             return true;
01460         if (wordlen == 10 && pg_strncasecmp(query, "tablespace", 10) == 0)
01461             return true;
01462 
01463         /* CREATE [UNIQUE] INDEX CONCURRENTLY isn't allowed in xacts */
01464         if (wordlen == 6 && pg_strncasecmp(query, "unique", 6) == 0)
01465         {
01466             query += wordlen;
01467 
01468             query = skip_white_space(query);
01469 
01470             wordlen = 0;
01471             while (isalpha((unsigned char) query[wordlen]))
01472                 wordlen += PQmblen(&query[wordlen], pset.encoding);
01473         }
01474 
01475         if (wordlen == 5 && pg_strncasecmp(query, "index", 5) == 0)
01476         {
01477             query += wordlen;
01478 
01479             query = skip_white_space(query);
01480 
01481             wordlen = 0;
01482             while (isalpha((unsigned char) query[wordlen]))
01483                 wordlen += PQmblen(&query[wordlen], pset.encoding);
01484 
01485             if (wordlen == 12 && pg_strncasecmp(query, "concurrently", 12) == 0)
01486                 return true;
01487         }
01488 
01489         return false;
01490     }
01491 
01492     /*
01493      * Note: these tests will match DROP SYSTEM and REINDEX TABLESPACE, which
01494      * aren't really valid commands so we don't care much. The other four
01495      * possible matches are correct.
01496      */
01497     if ((wordlen == 4 && pg_strncasecmp(query, "drop", 4) == 0) ||
01498         (wordlen == 7 && pg_strncasecmp(query, "reindex", 7) == 0))
01499     {
01500         query += wordlen;
01501 
01502         query = skip_white_space(query);
01503 
01504         wordlen = 0;
01505         while (isalpha((unsigned char) query[wordlen]))
01506             wordlen += PQmblen(&query[wordlen], pset.encoding);
01507 
01508         if (wordlen == 8 && pg_strncasecmp(query, "database", 8) == 0)
01509             return true;
01510         if (wordlen == 6 && pg_strncasecmp(query, "system", 6) == 0)
01511             return true;
01512         if (wordlen == 10 && pg_strncasecmp(query, "tablespace", 10) == 0)
01513             return true;
01514         return false;
01515     }
01516 
01517     /* DISCARD ALL isn't allowed in xacts, but other variants are allowed. */
01518     if (wordlen == 7 && pg_strncasecmp(query, "discard", 7) == 0)
01519     {
01520         query += wordlen;
01521 
01522         query = skip_white_space(query);
01523 
01524         wordlen = 0;
01525         while (isalpha((unsigned char) query[wordlen]))
01526             wordlen += PQmblen(&query[wordlen], pset.encoding);
01527 
01528         if (wordlen == 3 && pg_strncasecmp(query, "all", 3) == 0)
01529             return true;
01530         return false;
01531     }
01532 
01533     return false;
01534 }
01535 
01536 
01537 /*
01538  * Check whether the specified command is a SELECT (or VALUES).
01539  */
01540 static bool
01541 is_select_command(const char *query)
01542 {
01543     int         wordlen;
01544 
01545     /*
01546      * First advance over any whitespace, comments and left parentheses.
01547      */
01548     for (;;)
01549     {
01550         query = skip_white_space(query);
01551         if (query[0] == '(')
01552             query++;
01553         else
01554             break;
01555     }
01556 
01557     /*
01558      * Check word length (since "selectx" is not "select").
01559      */
01560     wordlen = 0;
01561     while (isalpha((unsigned char) query[wordlen]))
01562         wordlen += PQmblen(&query[wordlen], pset.encoding);
01563 
01564     if (wordlen == 6 && pg_strncasecmp(query, "select", 6) == 0)
01565         return true;
01566 
01567     if (wordlen == 6 && pg_strncasecmp(query, "values", 6) == 0)
01568         return true;
01569 
01570     return false;
01571 }
01572 
01573 
01574 /*
01575  * Test if the current user is a database superuser.
01576  *
01577  * Note: this will correctly detect superuserness only with a protocol-3.0
01578  * or newer backend; otherwise it will always say "false".
01579  */
01580 bool
01581 is_superuser(void)
01582 {
01583     const char *val;
01584 
01585     if (!pset.db)
01586         return false;
01587 
01588     val = PQparameterStatus(pset.db, "is_superuser");
01589 
01590     if (val && strcmp(val, "on") == 0)
01591         return true;
01592 
01593     return false;
01594 }
01595 
01596 
01597 /*
01598  * Test if the current session uses standard string literals.
01599  *
01600  * Note: With a pre-protocol-3.0 connection this will always say "false",
01601  * which should be the right answer.
01602  */
01603 bool
01604 standard_strings(void)
01605 {
01606     const char *val;
01607 
01608     if (!pset.db)
01609         return false;
01610 
01611     val = PQparameterStatus(pset.db, "standard_conforming_strings");
01612 
01613     if (val && strcmp(val, "on") == 0)
01614         return true;
01615 
01616     return false;
01617 }
01618 
01619 
01620 /*
01621  * Return the session user of the current connection.
01622  *
01623  * Note: this will correctly detect the session user only with a
01624  * protocol-3.0 or newer backend; otherwise it will return the
01625  * connection user.
01626  */
01627 const char *
01628 session_username(void)
01629 {
01630     const char *val;
01631 
01632     if (!pset.db)
01633         return NULL;
01634 
01635     val = PQparameterStatus(pset.db, "session_authorization");
01636     if (val)
01637         return val;
01638     else
01639         return PQuser(pset.db);
01640 }
01641 
01642 
01643 /* expand_tilde
01644  *
01645  * substitute '~' with HOME or '~username' with username's home dir
01646  *
01647  */
01648 void
01649 expand_tilde(char **filename)
01650 {
01651     if (!filename || !(*filename))
01652         return;
01653 
01654     /*
01655      * WIN32 doesn't use tilde expansion for file names. Also, it uses tilde
01656      * for short versions of long file names, though the tilde is usually
01657      * toward the end, not at the beginning.
01658      */
01659 #ifndef WIN32
01660 
01661     /* try tilde expansion */
01662     if (**filename == '~')
01663     {
01664         char       *fn;
01665         char        oldp,
01666                    *p;
01667         struct passwd *pw;
01668         char        home[MAXPGPATH];
01669 
01670         fn = *filename;
01671         *home = '\0';
01672 
01673         p = fn + 1;
01674         while (*p != '/' && *p != '\0')
01675             p++;
01676 
01677         oldp = *p;
01678         *p = '\0';
01679 
01680         if (*(fn + 1) == '\0')
01681             get_home_path(home);    /* ~ or ~/ only */
01682         else if ((pw = getpwnam(fn + 1)) != NULL)
01683             strlcpy(home, pw->pw_dir, sizeof(home));    /* ~user */
01684 
01685         *p = oldp;
01686         if (strlen(home) != 0)
01687         {
01688             char       *newfn;
01689 
01690             newfn = pg_malloc(strlen(home) + strlen(p) + 1);
01691             strcpy(newfn, home);
01692             strcat(newfn, p);
01693 
01694             free(fn);
01695             *filename = newfn;
01696         }
01697     }
01698 #endif
01699 
01700     return;
01701 }