@@ -832,10 +832,7 @@ ExecQueryTuples(const PGresult *result)
832
832
c ;
833
833
834
834
/*
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.
839
836
*/
840
837
pset .gexec_flag = false;
841
838
@@ -955,30 +952,39 @@ HandleCopyResult(PGresult **resultp, FILE *copystream)
955
952
956
953
/*
957
954
* PrintQueryStatus: report command status as required
958
- *
959
- * Note: Utility function for use by PrintQueryResult() only.
960
955
*/
961
956
static void
962
957
PrintQueryStatus (PGresult * result , FILE * printQueryFout )
963
958
{
964
959
char buf [16 ];
960
+ const char * cmdstatus = PQcmdStatus (result );
965
961
FILE * fout = printQueryFout ? printQueryFout : pset .queryFout ;
966
962
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
+
967
973
if (!pset .quiet )
968
974
{
969
975
if (pset .popt .topt .format == PRINT_HTML )
970
976
{
971
977
fputs ("<p>" , fout );
972
- html_escaped_print (PQcmdStatus ( result ) , fout );
978
+ html_escaped_print (cmdstatus , fout );
973
979
fputs ("</p>\n" , fout );
974
980
}
975
981
else
976
- fprintf (fout , "%s\n" , PQcmdStatus ( result ) );
982
+ fprintf (fout , "%s\n" , cmdstatus );
977
983
fflush (fout );
978
984
}
979
985
980
986
if (pset .logfile )
981
- fprintf (pset .logfile , "%s\n" , PQcmdStatus ( result ) );
987
+ fprintf (pset .logfile , "%s\n" , cmdstatus );
982
988
983
989
snprintf (buf , sizeof (buf ), "%u" , (unsigned int ) PQoidValue (result ));
984
990
SetVariable (pset .vars , "LASTOID" , buf );
@@ -988,8 +994,6 @@ PrintQueryStatus(PGresult *result, FILE *printQueryFout)
988
994
/*
989
995
* PrintQueryResult: print out (or store or execute) query result as required
990
996
*
991
- * Note: Utility function for use by SendQuery() only.
992
- *
993
997
* last is true if this is the last result of a command string.
994
998
* opt and printQueryFout are defined as for PrintQueryTuples.
995
999
* printStatusFout is where to send command status; NULL means pset.queryFout.
@@ -1002,7 +1006,6 @@ PrintQueryResult(PGresult *result, bool last,
1002
1006
FILE * printStatusFout )
1003
1007
{
1004
1008
bool success ;
1005
- const char * cmdstatus ;
1006
1009
1007
1010
if (!result )
1008
1011
return false;
@@ -1027,14 +1030,7 @@ PrintQueryResult(PGresult *result, bool last,
1027
1030
* status.
1028
1031
*/
1029
1032
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 );
1038
1034
1039
1035
break ;
1040
1036
@@ -1443,6 +1439,9 @@ DescribeQuery(const char *query, double *elapsed_msec)
1443
1439
* For other commands, the results are processed normally, depending on their
1444
1440
* status.
1445
1441
*
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
+ *
1446
1445
* Returns 1 on complete success, 0 on interrupt and -1 or errors. Possible
1447
1446
* failure modes include purely client-side problems; check the transaction
1448
1447
* status for the server-side opinion.
@@ -1488,11 +1487,21 @@ ExecQueryAndProcessResults(const char *query,
1488
1487
}
1489
1488
1490
1489
/*
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.
1496
1505
*/
1497
1506
if (pset .fetch_count > 0 && pset .show_all_results &&
1498
1507
!pset .crosstab_flag && !pset .gexec_flag &&
@@ -1644,8 +1653,8 @@ ExecQueryAndProcessResults(const char *query,
1644
1653
/* If we have a chunked result, collect and print all chunks */
1645
1654
if (result_status == PGRES_TUPLES_CHUNK )
1646
1655
{
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 ;
1649
1658
int64 total_tuples = 0 ;
1650
1659
bool is_pager = false;
1651
1660
int flush_error = 0 ;
@@ -1670,8 +1679,13 @@ ExecQueryAndProcessResults(const char *query,
1670
1679
do
1671
1680
{
1672
1681
/*
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.
1675
1689
*/
1676
1690
if (success && !flush_error && !cancel_pressed )
1677
1691
{
@@ -1710,6 +1724,12 @@ ExecQueryAndProcessResults(const char *query,
1710
1724
if (is_pager )
1711
1725
ClosePager (tuples_fout );
1712
1726
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
+
1713
1733
/*
1714
1734
* We must do a fake SetResultVariables(), since we don't have
1715
1735
* a PGresult corresponding to the whole query.
0 commit comments