]> granicus.if.org Git - postgresql/blobdiff - src/bin/psql/common.c
Show psql timing output even in quiet mode
[postgresql] / src / bin / psql / common.c
index ab1f03f310980dc614dcd1a66f27772e5796e6ff..ed929372420fba4c9bf9077cec112f103b15971c 100644 (file)
@@ -1,9 +1,9 @@
 /*
  * psql - the PostgreSQL interactive terminal
  *
- * Copyright (c) 2000-2008, PostgreSQL Global Development Group
+ * Copyright (c) 2000-2010, PostgreSQL Global Development Group
  *
- * $PostgreSQL: pgsql/src/bin/psql/common.c,v 1.139 2008/05/14 19:10:29 tgl Exp $
+ * $PostgreSQL: pgsql/src/bin/psql/common.c,v 1.147 2010/07/28 04:39:14 petere Exp $
  */
 #include "postgres_fe.h"
 #include "common.h"
@@ -555,8 +555,13 @@ PrintNotifications(void)
 
        while ((notify = PQnotifies(pset.db)))
        {
-               fprintf(pset.queryFout, _("Asynchronous notification \"%s\" received from server process with PID %d.\n"),
-                               notify->relname, notify->be_pid);
+               /* for backward compatibility, only show payload if nonempty */
+               if (notify->extra[0])
+                       fprintf(pset.queryFout, _("Asynchronous notification \"%s\" with payload \"%s\" received from server process with PID %d.\n"),
+                                       notify->relname, notify->extra, notify->be_pid);
+               else
+                       fprintf(pset.queryFout, _("Asynchronous notification \"%s\" received from server process with PID %d.\n"),
+                                       notify->relname, notify->be_pid);
                fflush(pset.queryFout);
                PQfreemem(notify);
        }
@@ -824,8 +829,8 @@ SendQuery(const char *query)
        {
                if (on_error_rollback_warning == false && pset.sversion < 80000)
                {
-                       fprintf(stderr, _("The server version (%d) does not support savepoints for ON_ERROR_ROLLBACK.\n"),
-                                       pset.sversion);
+                       fprintf(stderr, _("The server (version %d.%d) does not support savepoints for ON_ERROR_ROLLBACK.\n"),
+                                       pset.sversion / 10000, (pset.sversion / 100) % 100);
                        on_error_rollback_warning = true;
                }
                else
@@ -880,16 +885,20 @@ SendQuery(const char *query)
        /* If we made a temporary savepoint, possibly release/rollback */
        if (on_error_rollback_savepoint)
        {
-               PGresult   *svptres;
+               const char *svptcmd;
 
                transaction_status = PQtransactionStatus(pset.db);
 
-               /* We always rollback on an error */
                if (transaction_status == PQTRANS_INERROR)
-                       svptres = PQexec(pset.db, "ROLLBACK TO pg_psql_temporary_savepoint");
-               /* If they are no longer in a transaction, then do nothing */
+               {
+                       /* We always rollback on an error */
+                       svptcmd = "ROLLBACK TO pg_psql_temporary_savepoint";
+               }
                else if (transaction_status != PQTRANS_INTRANS)
-                       svptres = NULL;
+               {
+                       /* If they are no longer in a transaction, then do nothing */
+                       svptcmd = NULL;
+               }
                else
                {
                        /*
@@ -901,26 +910,33 @@ SendQuery(const char *query)
                                (strcmp(PQcmdStatus(results), "SAVEPOINT") == 0 ||
                                 strcmp(PQcmdStatus(results), "RELEASE") == 0 ||
                                 strcmp(PQcmdStatus(results), "ROLLBACK") == 0))
-                               svptres = NULL;
+                               svptcmd = NULL;
                        else
-                               svptres = PQexec(pset.db, "RELEASE pg_psql_temporary_savepoint");
+                               svptcmd = "RELEASE pg_psql_temporary_savepoint";
                }
-               if (svptres && PQresultStatus(svptres) != PGRES_COMMAND_OK)
+
+               if (svptcmd)
                {
-                       psql_error("%s", PQerrorMessage(pset.db));
-                       PQclear(results);
+                       PGresult   *svptres;
+
+                       svptres = PQexec(pset.db, svptcmd);
+                       if (PQresultStatus(svptres) != PGRES_COMMAND_OK)
+                       {
+                               psql_error("%s", PQerrorMessage(pset.db));
+                               PQclear(svptres);
+
+                               PQclear(results);
+                               ResetCancelConn();
+                               return false;
+                       }
                        PQclear(svptres);
-                       ResetCancelConn();
-                       return false;
                }
-
-               PQclear(svptres);
        }
 
        PQclear(results);
 
        /* Possible microtiming output */
-       if (OK && pset.timing && !pset.quiet)
+       if (OK && pset.timing)
                printf(_("Time: %.3f ms\n"), elapsed_msec);
 
        /* check for events that may occur during query execution */
@@ -966,6 +982,7 @@ ExecQueryUsingCursor(const char *query, double *elapsed_msec)
        char            fetch_cmd[64];
        instr_time      before,
                                after;
+       int                     flush_error;
 
        *elapsed_msec = 0;
 
@@ -1029,6 +1046,9 @@ ExecQueryUsingCursor(const char *query, double *elapsed_msec)
                }
        }
 
+       /* clear any pre-existing error indication on the output stream */
+       clearerr(pset.queryFout);
+
        for (;;)
        {
                if (pset.timing)
@@ -1080,19 +1100,29 @@ ExecQueryUsingCursor(const char *query, double *elapsed_msec)
 
                printQuery(results, &my_popt, pset.queryFout, pset.logfile);
 
-               /*
-                * Make sure to flush the output stream, so intermediate results are
-                * visible to the client immediately.
-                */
-               fflush(pset.queryFout);
+               PQclear(results);
 
                /* after the first result set, disallow header decoration */
                my_popt.topt.start_table = false;
                my_popt.topt.prior_records += ntuples;
 
-               PQclear(results);
+               /*
+                * Make sure to flush the output stream, so intermediate results are
+                * visible to the client immediately.  We check the results because if
+                * the pager dies/exits/etc, there's no sense throwing more data at
+                * it.
+                */
+               flush_error = fflush(pset.queryFout);
 
-               if (ntuples < pset.fetch_count || cancel_pressed)
+               /*
+                * Check if we are at the end, if a cancel was pressed, or if there
+                * were any errors either trying to flush out the results, or more
+                * generally on the output stream at all.  If we hit any errors
+                * writing things to the stream, we presume $PAGER has disappeared and
+                * stop bothering to pull down more data.
+                */
+               if (ntuples < pset.fetch_count || cancel_pressed || flush_error ||
+                       ferror(pset.queryFout))
                        break;
        }