X-Git-Url: https://granicus.if.org/sourcecode?a=blobdiff_plain;f=src%2Fbin%2Fpsql%2Fcommon.c;h=ed929372420fba4c9bf9077cec112f103b15971c;hb=4ff9c8dd48b265d925be8bf90ac65c34a249c7b5;hp=ab1f03f310980dc614dcd1a66f27772e5796e6ff;hpb=3bc25384d7a698f25e418bdc5aa7cdd038477d9c;p=postgresql diff --git a/src/bin/psql/common.c b/src/bin/psql/common.c index ab1f03f310..ed92937242 100644 --- a/src/bin/psql/common.c +++ b/src/bin/psql/common.c @@ -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; }