diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml
index 880d3d0b32..66dd6801a0 100644
--- a/doc/src/sgml/ref/psql-ref.sgml
+++ b/doc/src/sgml/ref/psql-ref.sgml
@@ -3544,13 +3544,15 @@ testdb=> \setenv LESS -imx4F
- \watch [ i[nterval]=seconds ] [ c[ount]=times ] [ seconds ]
+ \watch [ i[nterval]=seconds ] [ c[ount]=times ] [ zero ] [ seconds ]
Repeatedly execute the current query buffer (as \g does)
until interrupted, or the query fails, or the execution count limit
- (if given) is reached. Wait the specified number of
- seconds (default 2) between executions. For backwards compatibility,
+ (if given) is reached. If the zero
+ argument is used, execution stops when the query returns zero rows.
+ Wait the specified number of seconds (default 2) between executions.
+ For backwards compatibility,
seconds can be specified
with or without an interval= prefix.
Each query result is
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index 511debbe81..679365a26e 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -162,7 +162,7 @@ static bool do_connect(enum trivalue reuse_previous_specification,
static bool do_edit(const char *filename_arg, PQExpBuffer query_buf,
int lineno, bool discard_on_quit, bool *edited);
static bool do_shell(const char *command);
-static bool do_watch(PQExpBuffer query_buf, double sleep, int iter);
+static bool do_watch(PQExpBuffer query_buf, double sleep, int iter, bool zero_if_empty);
static bool lookup_object_oid(EditableObjectType obj_type, const char *desc,
Oid *obj_oid);
static bool get_create_object_cmd(EditableObjectType obj_type, Oid oid,
@@ -2773,13 +2773,14 @@ exec_command_watch(PsqlScanState scan_state, bool active_branch,
{
bool have_sleep = false;
bool have_iter = false;
+ bool zero_if_empty = false;
double sleep = 2;
int iter = 0;
/*
- * Parse arguments. We allow either an unlabeled interval or
- * "name=value", where name is from the set ('i', 'interval', 'c',
- * 'count').
+ * Parse arguments. We allow either an unlabeled interval, the
+ * keyword "zero", or "name=value", where name is from the set ('i',
+ * 'interval', 'c', 'count').
*/
while (success)
{
@@ -2842,6 +2843,10 @@ exec_command_watch(PsqlScanState scan_state, bool active_branch,
success = false;
}
}
+ else if (strncmp("zero", opt, strlen("zero")) == 0)
+ {
+ zero_if_empty = true;
+ }
else
{
/* Unlabeled argument: take it as interval */
@@ -2872,7 +2877,7 @@ exec_command_watch(PsqlScanState scan_state, bool active_branch,
/* If query_buf is empty, recall and execute previous query */
(void) copy_previous_query(query_buf, previous_buf);
- success = do_watch(query_buf, sleep, iter);
+ success = do_watch(query_buf, sleep, iter, zero_if_empty);
}
/* Reset the query buffer as though for \r */
@@ -5142,7 +5147,7 @@ do_shell(const char *command)
* onto a bunch of exec_command's variables to silence stupider compilers.
*/
static bool
-do_watch(PQExpBuffer query_buf, double sleep, int iter)
+do_watch(PQExpBuffer query_buf, double sleep, int iter, bool zero_if_empty)
{
long sleep_ms = (long) (sleep * 1000);
printQueryOpt myopt = pset.popt;
@@ -5272,7 +5277,7 @@ do_watch(PQExpBuffer query_buf, double sleep, int iter)
myopt.title = title;
/* Run the query and print out the result */
- res = PSQLexecWatch(query_buf->data, &myopt, pagerpipe);
+ res = PSQLexecWatch(query_buf->data, &myopt, pagerpipe, zero_if_empty);
/*
* PSQLexecWatch handles the case where we can no longer repeat the
diff --git a/src/bin/psql/common.c b/src/bin/psql/common.c
index 5973df2e39..4530dbcfc7 100644
--- a/src/bin/psql/common.c
+++ b/src/bin/psql/common.c
@@ -36,6 +36,7 @@ static int ExecQueryAndProcessResults(const char *query,
double *elapsed_msec,
bool *svpt_gone_p,
bool is_watch,
+ bool zero_if_empty,
const printQueryOpt *opt,
FILE *printQueryFout);
static bool command_no_begin(const char *query);
@@ -632,7 +633,7 @@ PSQLexec(const char *query)
* e.g., because of the interrupt, -1 on error.
*/
int
-PSQLexecWatch(const char *query, const printQueryOpt *opt, FILE *printQueryFout)
+PSQLexecWatch(const char *query, const printQueryOpt *opt, FILE *printQueryFout, bool zero_if_empty)
{
bool timing = pset.timing;
double elapsed_msec = 0;
@@ -646,7 +647,7 @@ PSQLexecWatch(const char *query, const printQueryOpt *opt, FILE *printQueryFout)
SetCancelConn(pset.db);
- res = ExecQueryAndProcessResults(query, &elapsed_msec, NULL, true, opt, printQueryFout);
+ res = ExecQueryAndProcessResults(query, &elapsed_msec, NULL, true, zero_if_empty, opt, printQueryFout);
ResetCancelConn();
@@ -1134,7 +1135,7 @@ SendQuery(const char *query)
pset.crosstab_flag || !is_select_command(query))
{
/* Default fetch-it-all-and-print mode */
- OK = (ExecQueryAndProcessResults(query, &elapsed_msec, &svpt_gone, false, NULL, NULL) > 0);
+ OK = (ExecQueryAndProcessResults(query, &elapsed_msec, &svpt_gone, false, false, NULL, NULL) > 0);
}
else
{
@@ -1415,11 +1416,12 @@ DescribeQuery(const char *query, double *elapsed_msec)
static int
ExecQueryAndProcessResults(const char *query,
double *elapsed_msec, bool *svpt_gone_p,
- bool is_watch,
+ bool is_watch, bool zero_if_empty,
const printQueryOpt *opt, FILE *printQueryFout)
{
bool timing = pset.timing;
bool success;
+ bool return_empty = false;
instr_time before,
after;
PGresult *result;
@@ -1461,6 +1463,10 @@ ExecQueryAndProcessResults(const char *query,
/* first result */
result = PQgetResult(pset.db);
+ if (zero_if_empty && PQntuples(result) < 1)
+ {
+ return_empty = true;
+ }
while (result != NULL)
{
@@ -1683,7 +1689,7 @@ ExecQueryAndProcessResults(const char *query,
if (!CheckConnection())
return -1;
- return cancel_pressed ? 0 : success ? 1 : -1;
+ return (cancel_pressed || return_empty) ? 0 : success ? 1 : -1;
}
diff --git a/src/bin/psql/common.h b/src/bin/psql/common.h
index 812b94a977..36ccb39ac0 100644
--- a/src/bin/psql/common.h
+++ b/src/bin/psql/common.h
@@ -32,7 +32,7 @@ extern void psql_setup_cancel_handler(void);
extern void SetShellResultVariables(int wait_result);
extern PGresult *PSQLexec(const char *query);
-extern int PSQLexecWatch(const char *query, const printQueryOpt *opt, FILE *printQueryFout);
+extern int PSQLexecWatch(const char *query, const printQueryOpt *opt, FILE *printQueryFout, bool zero_if_empty);
extern bool SendQuery(const char *query);