]> 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 76e0c0e6b890282fedd552b92c72c90f044ff693..ed929372420fba4c9bf9077cec112f103b15971c 100644 (file)
@@ -1,9 +1,9 @@
 /*
  * psql - the PostgreSQL interactive terminal
  *
- * Copyright (c) 2000-2006, PostgreSQL Global Development Group
+ * Copyright (c) 2000-2010, PostgreSQL Global Development Group
  *
- * $PostgreSQL: pgsql/src/bin/psql/common.c,v 1.131 2006/12/16 00:38:43 adunstan 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"
 #include <win32.h>
 #endif
 
+#include "portability/instr_time.h"
+
 #include "pqsignal.h"
 
 #include "settings.h"
 #include "command.h"
 #include "copy.h"
-#include "mb/pg_wchar.h"
 #include "mbprint.h"
 
 
@@ -554,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);
        }
@@ -823,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
@@ -845,11 +851,11 @@ SendQuery(const char *query)
        if (pset.fetch_count <= 0 || !is_select_command(query))
        {
                /* Default fetch-it-all-and-print mode */
-               TimevalStruct before,
+               instr_time      before,
                                        after;
 
                if (pset.timing)
-                       GETTIMEOFDAY(&before);
+                       INSTR_TIME_SET_CURRENT(before);
 
                results = PQexec(pset.db, query);
 
@@ -859,8 +865,9 @@ SendQuery(const char *query)
 
                if (pset.timing)
                {
-                       GETTIMEOFDAY(&after);
-                       elapsed_msec = DIFF_MSEC(&after, &before);
+                       INSTR_TIME_SET_CURRENT(after);
+                       INSTR_TIME_SUBTRACT(after, before);
+                       elapsed_msec = INSTR_TIME_GET_MILLISEC(after);
                }
 
                /* but printing results isn't: */
@@ -878,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
                {
                        /*
@@ -899,20 +910,27 @@ 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);
@@ -962,8 +980,9 @@ ExecQueryUsingCursor(const char *query, double *elapsed_msec)
        bool            did_pager = false;
        int                     ntuples;
        char            fetch_cmd[64];
-       TimevalStruct before,
+       instr_time      before,
                                after;
+       int                     flush_error;
 
        *elapsed_msec = 0;
 
@@ -973,7 +992,7 @@ ExecQueryUsingCursor(const char *query, double *elapsed_msec)
        my_popt.topt.prior_records = 0;
 
        if (pset.timing)
-               GETTIMEOFDAY(&before);
+               INSTR_TIME_SET_CURRENT(before);
 
        /* if we're not in a transaction, start one */
        if (PQtransactionStatus(pset.db) == PQTRANS_IDLE)
@@ -1002,8 +1021,9 @@ ExecQueryUsingCursor(const char *query, double *elapsed_msec)
 
        if (pset.timing)
        {
-               GETTIMEOFDAY(&after);
-               *elapsed_msec += DIFF_MSEC(&after, &before);
+               INSTR_TIME_SET_CURRENT(after);
+               INSTR_TIME_SUBTRACT(after, before);
+               *elapsed_msec += INSTR_TIME_GET_MILLISEC(after);
        }
 
        snprintf(fetch_cmd, sizeof(fetch_cmd),
@@ -1026,18 +1046,22 @@ ExecQueryUsingCursor(const char *query, double *elapsed_msec)
                }
        }
 
+       /* clear any pre-existing error indication on the output stream */
+       clearerr(pset.queryFout);
+
        for (;;)
        {
                if (pset.timing)
-                       GETTIMEOFDAY(&before);
+                       INSTR_TIME_SET_CURRENT(before);
 
                /* get FETCH_COUNT tuples at a time */
                results = PQexec(pset.db, fetch_cmd);
 
                if (pset.timing)
                {
-                       GETTIMEOFDAY(&after);
-                       *elapsed_msec += DIFF_MSEC(&after, &before);
+                       INSTR_TIME_SET_CURRENT(after);
+                       INSTR_TIME_SUBTRACT(after, before);
+                       *elapsed_msec += INSTR_TIME_GET_MILLISEC(after);
                }
 
                if (PQresultStatus(results) != PGRES_TUPLES_OK)
@@ -1076,13 +1100,29 @@ ExecQueryUsingCursor(const char *query, double *elapsed_msec)
 
                printQuery(results, &my_popt, pset.queryFout, pset.logfile);
 
+               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;
        }
 
@@ -1107,7 +1147,7 @@ ExecQueryUsingCursor(const char *query, double *elapsed_msec)
 
 cleanup:
        if (pset.timing)
-               GETTIMEOFDAY(&before);
+               INSTR_TIME_SET_CURRENT(before);
 
        /*
         * We try to close the cursor on either success or failure, but on failure
@@ -1132,8 +1172,9 @@ cleanup:
 
        if (pset.timing)
        {
-               GETTIMEOFDAY(&after);
-               *elapsed_msec += DIFF_MSEC(&after, &before);
+               INSTR_TIME_SET_CURRENT(after);
+               INSTR_TIME_SUBTRACT(after, before);
+               *elapsed_msec += INSTR_TIME_GET_MILLISEC(after);
        }
 
        return OK;
@@ -1497,7 +1538,7 @@ expand_tilde(char **filename)
                if (*(fn + 1) == '\0')
                        get_home_path(home);    /* ~ or ~/ only */
                else if ((pw = getpwnam(fn + 1)) != NULL)
-                       StrNCpy(home, pw->pw_dir, MAXPGPATH);           /* ~user */
+                       strlcpy(home, pw->pw_dir, sizeof(home));        /* ~user */
 
                *p = oldp;
                if (strlen(home) != 0)