@@ -832,10 +832,7 @@ ExecQueryTuples(const PGresult *result)
832832 c ;
833833
834834 /*
835- * We must turn off gexec_flag to avoid infinite recursion. Note that
836- * this allows ExecQueryUsingCursor to be applied to the individual query
837- * results. SendQuery prevents it from being applied when fetching the
838- * queries-to-execute, because it can't handle recursion either.
835+ * We must turn off gexec_flag to avoid infinite recursion.
839836 */
840837 pset .gexec_flag = false;
841838
@@ -955,30 +952,39 @@ HandleCopyResult(PGresult **resultp, FILE *copystream)
955952
956953/*
957954 * PrintQueryStatus: report command status as required
958- *
959- * Note: Utility function for use by PrintQueryResult() only.
960955 */
961956static void
962957PrintQueryStatus (PGresult * result , FILE * printQueryFout )
963958{
964959 char buf [16 ];
960+ const char * cmdstatus = PQcmdStatus (result );
965961 FILE * fout = printQueryFout ? printQueryFout : pset .queryFout ;
966962
963+ /* Do nothing if it's a TUPLES_OK result that isn't from RETURNING */
964+ if (PQresultStatus (result ) == PGRES_TUPLES_OK )
965+ {
966+ if (!(strncmp (cmdstatus , "INSERT" , 6 ) == 0 ||
967+ strncmp (cmdstatus , "UPDATE" , 6 ) == 0 ||
968+ strncmp (cmdstatus , "DELETE" , 6 ) == 0 ||
969+ strncmp (cmdstatus , "MERGE" , 5 ) == 0 ))
970+ return ;
971+ }
972+
967973 if (!pset .quiet )
968974 {
969975 if (pset .popt .topt .format == PRINT_HTML )
970976 {
971977 fputs ("<p>" , fout );
972- html_escaped_print (PQcmdStatus ( result ) , fout );
978+ html_escaped_print (cmdstatus , fout );
973979 fputs ("</p>\n" , fout );
974980 }
975981 else
976- fprintf (fout , "%s\n" , PQcmdStatus ( result ) );
982+ fprintf (fout , "%s\n" , cmdstatus );
977983 fflush (fout );
978984 }
979985
980986 if (pset .logfile )
981- fprintf (pset .logfile , "%s\n" , PQcmdStatus ( result ) );
987+ fprintf (pset .logfile , "%s\n" , cmdstatus );
982988
983989 snprintf (buf , sizeof (buf ), "%u" , (unsigned int ) PQoidValue (result ));
984990 SetVariable (pset .vars , "LASTOID" , buf );
@@ -988,8 +994,6 @@ PrintQueryStatus(PGresult *result, FILE *printQueryFout)
988994/*
989995 * PrintQueryResult: print out (or store or execute) query result as required
990996 *
991- * Note: Utility function for use by SendQuery() only.
992- *
993997 * last is true if this is the last result of a command string.
994998 * opt and printQueryFout are defined as for PrintQueryTuples.
995999 * printStatusFout is where to send command status; NULL means pset.queryFout.
@@ -1002,7 +1006,6 @@ PrintQueryResult(PGresult *result, bool last,
10021006 FILE * printStatusFout )
10031007{
10041008 bool success ;
1005- const char * cmdstatus ;
10061009
10071010 if (!result )
10081011 return false;
@@ -1027,14 +1030,7 @@ PrintQueryResult(PGresult *result, bool last,
10271030 * status.
10281031 */
10291032 if (last || pset .show_all_results )
1030- {
1031- cmdstatus = PQcmdStatus (result );
1032- if (strncmp (cmdstatus , "INSERT" , 6 ) == 0 ||
1033- strncmp (cmdstatus , "UPDATE" , 6 ) == 0 ||
1034- strncmp (cmdstatus , "DELETE" , 6 ) == 0 ||
1035- strncmp (cmdstatus , "MERGE" , 5 ) == 0 )
1036- PrintQueryStatus (result , printStatusFout );
1037- }
1033+ PrintQueryStatus (result , printStatusFout );
10381034
10391035 break ;
10401036
@@ -1443,6 +1439,9 @@ DescribeQuery(const char *query, double *elapsed_msec)
14431439 * For other commands, the results are processed normally, depending on their
14441440 * status.
14451441 *
1442+ * When invoked from \watch, is_watch is true and min_rows is the value
1443+ * of that option, or 0 if it wasn't set.
1444+ *
14461445 * Returns 1 on complete success, 0 on interrupt and -1 or errors. Possible
14471446 * failure modes include purely client-side problems; check the transaction
14481447 * status for the server-side opinion.
@@ -1488,11 +1487,21 @@ ExecQueryAndProcessResults(const char *query,
14881487 }
14891488
14901489 /*
1491- * Fetch the result in chunks if FETCH_COUNT is set. But we don't enable
1492- * chunking if SHOW_ALL_RESULTS is false, since that requires us to
1493- * accumulate all rows before we can tell what should be displayed, which
1494- * would counter the idea of FETCH_COUNT. Chunking is also disabled when
1495- * \crosstab, \gexec, \gset or \watch is used.
1490+ * Fetch the result in chunks if FETCH_COUNT is set, except when:
1491+ *
1492+ * * SHOW_ALL_RESULTS is false, since that requires us to complete the
1493+ * query before we can tell if its results should be displayed.
1494+ *
1495+ * * We're doing \crosstab, which likewise needs to see all the rows at
1496+ * once.
1497+ *
1498+ * * We're doing \gexec: we must complete the data fetch to make the
1499+ * connection free for issuing the resulting commands.
1500+ *
1501+ * * We're doing \gset: only one result row is allowed anyway.
1502+ *
1503+ * * We're doing \watch: users probably don't want us to force use of the
1504+ * pager for that, plus chunking could break the min_rows check.
14961505 */
14971506 if (pset .fetch_count > 0 && pset .show_all_results &&
14981507 !pset .crosstab_flag && !pset .gexec_flag &&
@@ -1644,8 +1653,8 @@ ExecQueryAndProcessResults(const char *query,
16441653 /* If we have a chunked result, collect and print all chunks */
16451654 if (result_status == PGRES_TUPLES_CHUNK )
16461655 {
1647- FILE * tuples_fout = printQueryFout ? printQueryFout : stdout ;
1648- printQueryOpt my_popt = pset .popt ;
1656+ FILE * tuples_fout = printQueryFout ? printQueryFout : pset . queryFout ;
1657+ printQueryOpt my_popt = opt ? * opt : pset .popt ;
16491658 int64 total_tuples = 0 ;
16501659 bool is_pager = false;
16511660 int flush_error = 0 ;
@@ -1670,8 +1679,13 @@ ExecQueryAndProcessResults(const char *query,
16701679 do
16711680 {
16721681 /*
1673- * display the current chunk of results, unless the output
1674- * stream stopped working or we got cancelled
1682+ * Display the current chunk of results, unless the output
1683+ * stream stopped working or we got cancelled. We skip use of
1684+ * PrintQueryResult and go directly to printQuery, so that we
1685+ * can pass the correct is_pager value and because we don't
1686+ * want PrintQueryStatus to happen yet. Above, we rejected
1687+ * use of chunking for all cases in which PrintQueryResult
1688+ * would send the result to someplace other than printQuery.
16751689 */
16761690 if (success && !flush_error && !cancel_pressed )
16771691 {
@@ -1710,6 +1724,12 @@ ExecQueryAndProcessResults(const char *query,
17101724 if (is_pager )
17111725 ClosePager (tuples_fout );
17121726
1727+ /*
1728+ * It's possible the data is from a RETURNING clause, in which
1729+ * case we need to print query status.
1730+ */
1731+ PrintQueryStatus (result , printQueryFout );
1732+
17131733 /*
17141734 * We must do a fake SetResultVariables(), since we don't have
17151735 * a PGresult corresponding to the whole query.
0 commit comments