Improve handling of psql \watch's interval argument
authorMichael Paquier <[email protected]>
Thu, 16 Mar 2023 00:32:36 +0000 (09:32 +0900)
committerMichael Paquier <[email protected]>
Thu, 16 Mar 2023 00:32:36 +0000 (09:32 +0900)
A failure in parsing the interval value defined in the \watch command
was silently switched to 1s of interval between two queries, which can
be confusing.  This commit improves the error handling, and a couple of
tests are added to check after:
- An incorrect value.
- An out-of-range value.
- A negative value.

A value of zero is able to work now, meaning that there is no interval
of time between two queries in a \watch loop.  No backpatch is done, as
it could break existing applications.

Author: Andrey Borodin
Reviewed-by: Kyotaro Horiguchi, Nathan Bossart, Michael Paquier
Discussion: https://postgr.es/m/CAAhFRxiZ2-n_L1ErMm9AZjgmUK=qS6VHb+0SaMn8sqqbhF7How@mail.gmail.com

src/bin/psql/command.c
src/bin/psql/t/001_basic.pl

index 955397ee9dc803f065d9e2089f918f2d75637505..61ec049f0545c4dad991e84dff872c21f8cf0342 100644 (file)
@@ -2776,9 +2776,18 @@ exec_command_watch(PsqlScanState scan_state, bool active_branch,
                /* Convert optional sleep-length argument */
                if (opt)
                {
-                       sleep = strtod(opt, NULL);
-                       if (sleep <= 0)
-                               sleep = 1;
+                       char       *opt_end;
+
+                       errno = 0;
+                       sleep = strtod(opt, &opt_end);
+                       if (sleep < 0 || *opt_end || errno == ERANGE)
+                       {
+                               pg_log_error("\\watch: incorrect interval value '%s'", opt);
+                               free(opt);
+                               resetPQExpBuffer(query_buf);
+                               psql_scan_reset(scan_state);
+                               return PSQL_CMD_ERROR;
+                       }
                        free(opt);
                }
 
@@ -5183,6 +5192,9 @@ do_watch(PQExpBuffer query_buf, double sleep)
                if (pagerpipe && ferror(pagerpipe))
                        break;
 
+               if (sleep == 0)
+                       continue;
+
 #ifdef WIN32
 
                /*
index 0f394420b268c558f0cc949fa76dfe1056b679d7..64ce0120621a9c3efc1e756cf586c4c5a09c7132 100644 (file)
@@ -350,4 +350,21 @@ psql_like(
        '\copy from with DEFAULT'
 );
 
+# Check \watch errors
+psql_fails_like(
+       $node,
+       'SELECT 1;\watch -10',
+       qr/incorrect interval value '-10'/,
+       '\watch, negative interval');
+psql_fails_like(
+       $node,
+       'SELECT 1;\watch 10ab',
+       qr/incorrect interval value '10ab'/,
+       '\watch incorrect interval');
+psql_fails_like(
+       $node,
+       'SELECT 1;\watch 10e400',
+       qr/incorrect interval value '10e400'/,
+       '\watch out-of-range interval');
+
 done_testing();