From 47d6d4485bca56900dee8ae6f7ad82fa98efcc21 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Fri, 28 May 2010 20:02:32 +0000
Subject: [PATCH] Abort a FETCH_COUNT-controlled query if we observe any I/O
 error on the output stream.  This typically indicates that the user quit out
 of $PAGER, or that we are writing to a file and ran out of disk space.  In
 either case we shouldn't bother to continue fetching data.

Stephen Frost
---
 src/bin/psql/common.c | 30 ++++++++++++++++++++++--------
 1 file changed, 22 insertions(+), 8 deletions(-)

diff --git a/src/bin/psql/common.c b/src/bin/psql/common.c
index 9661f0cd803..cdb071f85e2 100644
--- a/src/bin/psql/common.c
+++ b/src/bin/psql/common.c
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 2000-2010, PostgreSQL Global Development Group
  *
- * $PostgreSQL: pgsql/src/bin/psql/common.c,v 1.144 2010/02/16 22:34:50 tgl Exp $
+ * $PostgreSQL: pgsql/src/bin/psql/common.c,v 1.145 2010/05/28 20:02:32 tgl Exp $
  */
 #include "postgres_fe.h"
 #include "common.h"
@@ -982,6 +982,7 @@ ExecQueryUsingCursor(const char *query, double *elapsed_msec)
 	char		fetch_cmd[64];
 	instr_time	before,
 				after;
+	int			flush_error;
 
 	*elapsed_msec = 0;
 
@@ -1045,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)
@@ -1096,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;
 	}
 
-- 
GitLab