@@ -162,7 +162,7 @@ static bool do_connect(enum trivalue reuse_previous_specification,
162
162
static bool do_edit (const char * filename_arg , PQExpBuffer query_buf ,
163
163
int lineno , bool discard_on_quit , bool * edited );
164
164
static bool do_shell (const char * command );
165
- static bool do_watch (PQExpBuffer query_buf , double sleep );
165
+ static bool do_watch (PQExpBuffer query_buf , double sleep , int iter );
166
166
static bool lookup_object_oid (EditableObjectType obj_type , const char * desc ,
167
167
Oid * obj_oid );
168
168
static bool get_create_object_cmd (EditableObjectType obj_type , Oid oid ,
@@ -2759,7 +2759,8 @@ exec_command_write(PsqlScanState scan_state, bool active_branch,
2759
2759
}
2760
2760
2761
2761
/*
2762
- * \watch -- execute a query every N seconds
2762
+ * \watch -- execute a query every N seconds.
2763
+ * Optionally, stop after M iterations.
2763
2764
*/
2764
2765
static backslashResult
2765
2766
exec_command_watch (PsqlScanState scan_state , bool active_branch ,
@@ -2769,32 +2770,109 @@ exec_command_watch(PsqlScanState scan_state, bool active_branch,
2769
2770
2770
2771
if (active_branch )
2771
2772
{
2772
- char * opt = psql_scan_slash_option ( scan_state ,
2773
- OT_NORMAL , NULL , true) ;
2773
+ bool have_sleep = false;
2774
+ bool have_iter = false ;
2774
2775
double sleep = 2 ;
2776
+ int iter = 0 ;
2775
2777
2776
- /* Convert optional sleep-length argument */
2777
- if (opt )
2778
+ /*
2779
+ * Parse arguments. We allow either an unlabeled interval or
2780
+ * "name=value", where name is from the set ('i', 'interval', 'c',
2781
+ * 'count').
2782
+ */
2783
+ while (success )
2778
2784
{
2785
+ char * opt = psql_scan_slash_option (scan_state ,
2786
+ OT_NORMAL , NULL , true);
2787
+ char * valptr ;
2779
2788
char * opt_end ;
2780
2789
2781
- errno = 0 ;
2782
- sleep = strtod (opt , & opt_end );
2783
- if (sleep < 0 || * opt_end || errno == ERANGE )
2790
+ if (!opt )
2791
+ break ; /* no more arguments */
2792
+
2793
+ valptr = strchr (opt , '=' );
2794
+ if (valptr )
2784
2795
{
2785
- pg_log_error ("\\watch: incorrect interval value '%s'" , opt );
2786
- free (opt );
2787
- resetPQExpBuffer (query_buf );
2788
- psql_scan_reset (scan_state );
2789
- return PSQL_CMD_ERROR ;
2796
+ /* Labeled argument */
2797
+ valptr ++ ;
2798
+ if (strncmp ("i=" , opt , strlen ("i=" )) == 0 ||
2799
+ strncmp ("interval=" , opt , strlen ("interval=" )) == 0 )
2800
+ {
2801
+ if (have_sleep )
2802
+ {
2803
+ pg_log_error ("\\watch: interval value is specified more than once" );
2804
+ success = false;
2805
+ }
2806
+ else
2807
+ {
2808
+ have_sleep = true;
2809
+ errno = 0 ;
2810
+ sleep = strtod (valptr , & opt_end );
2811
+ if (sleep < 0 || * opt_end || errno == ERANGE )
2812
+ {
2813
+ pg_log_error ("\\watch: incorrect interval value \"%s\"" , valptr );
2814
+ success = false;
2815
+ }
2816
+ }
2817
+ }
2818
+ else if (strncmp ("c=" , opt , strlen ("c=" )) == 0 ||
2819
+ strncmp ("count=" , opt , strlen ("count=" )) == 0 )
2820
+ {
2821
+ if (have_iter )
2822
+ {
2823
+ pg_log_error ("\\watch: iteration count is specified more than once" );
2824
+ success = false;
2825
+ }
2826
+ else
2827
+ {
2828
+ have_iter = true;
2829
+ errno = 0 ;
2830
+ iter = strtoint (valptr , & opt_end , 10 );
2831
+ if (iter <= 0 || * opt_end || errno == ERANGE )
2832
+ {
2833
+ pg_log_error ("\\watch: incorrect iteration count \"%s\"" , valptr );
2834
+ success = false;
2835
+ }
2836
+ }
2837
+ }
2838
+ else
2839
+ {
2840
+ pg_log_error ("\\watch: unrecognized parameter \"%s\"" , opt );
2841
+ success = false;
2842
+ }
2843
+ }
2844
+ else
2845
+ {
2846
+ /* Unlabeled argument: take it as interval */
2847
+ if (have_sleep )
2848
+ {
2849
+ pg_log_error ("\\watch: interval value is specified more than once" );
2850
+ success = false;
2851
+ }
2852
+ else
2853
+ {
2854
+ have_sleep = true;
2855
+ errno = 0 ;
2856
+ sleep = strtod (opt , & opt_end );
2857
+ if (sleep < 0 || * opt_end || errno == ERANGE )
2858
+ {
2859
+ pg_log_error ("\\watch: incorrect interval value \"%s\"" , opt );
2860
+ success = false;
2861
+ }
2862
+ }
2790
2863
}
2864
+
2791
2865
free (opt );
2792
2866
}
2793
2867
2794
- /* If query_buf is empty, recall and execute previous query */
2795
- (void ) copy_previous_query (query_buf , previous_buf );
2868
+ /* If we parsed arguments successfully, do the command */
2869
+ if (success )
2870
+ {
2871
+ /* If query_buf is empty, recall and execute previous query */
2872
+ (void ) copy_previous_query (query_buf , previous_buf );
2796
2873
2797
- success = do_watch (query_buf , sleep );
2874
+ success = do_watch (query_buf , sleep , iter );
2875
+ }
2798
2876
2799
2877
/* Reset the query buffer as though for \r */
2800
2878
resetPQExpBuffer (query_buf );
@@ -5071,7 +5149,7 @@ do_shell(const char *command)
5071
5149
* onto a bunch of exec_command's variables to silence stupider compilers.
5072
5150
*/
5073
5151
static bool
5074
- do_watch (PQExpBuffer query_buf , double sleep )
5152
+ do_watch (PQExpBuffer query_buf , double sleep , int iter )
5075
5153
{
5076
5154
long sleep_ms = (long ) (sleep * 1000 );
5077
5155
printQueryOpt myopt = pset .popt ;
@@ -5204,6 +5282,10 @@ do_watch(PQExpBuffer query_buf, double sleep)
5204
5282
if (res <= 0 )
5205
5283
break ;
5206
5284
5285
+ /* If we have iteration count, check that it's not exceeded yet */
5286
+ if (iter && (-- iter <= 0 ))
5287
+ break ;
5288
+
5207
5289
if (pagerpipe && ferror (pagerpipe ))
5208
5290
break ;
5209
5291
0 commit comments