From a07e911f89bc72992edd228fa3c9326a58060cb6 Mon Sep 17 00:00:00 2001 From: "Andrey M. Borodin" Date: Thu, 16 Feb 2023 15:07:50 -0800 Subject: [PATCH] Add iteration count argument to psql \watch command If the argument is not provided - continue to \watch forever. --- src/bin/psql/command.c | 39 +++++++++++++++++++++++++----- src/bin/psql/help.c | 2 +- src/test/regress/expected/psql.out | 2 +- src/test/regress/sql/psql.sql | 2 +- 4 files changed, 36 insertions(+), 9 deletions(-) diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c index b5201edf55..482ff557f0 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); +static bool do_watch(PQExpBuffer query_buf, double sleep, int iter); 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, @@ -2759,7 +2759,8 @@ exec_command_write(PsqlScanState scan_state, bool active_branch, } /* - * \watch -- execute a query every N seconds + * \watch -- execute a query every N seconds. + * Optionally for M iteration. */ static backslashResult exec_command_watch(PsqlScanState scan_state, bool active_branch, @@ -2772,20 +2773,41 @@ exec_command_watch(PsqlScanState scan_state, bool active_branch, char *opt = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, true); double sleep = 2; + int iter = 0; /* Convert optional sleep-length argument */ if (opt) { sleep = strtod(opt, NULL); if (sleep <= 0) - sleep = 1; + { + pg_log_error("Invalid watch argument %s", opt); + resetPQExpBuffer(query_buf); + return PSQL_CMD_ERROR; + } + free(opt); + + /* Check if iteration count is given */ + opt = psql_scan_slash_option(scan_state, + OT_NORMAL, NULL, true); + if (opt) + { + iter = strtol(opt, NULL, 10); + if (iter <= 0) + { + pg_log_error("Invalid iteration count %s", opt); + resetPQExpBuffer(query_buf); + return PSQL_CMD_ERROR; + } + free(opt); + } } /* If query_buf is empty, recall and execute previous query */ (void) copy_previous_query(query_buf, previous_buf); - success = do_watch(query_buf, sleep); + success = do_watch(query_buf, sleep, iter); /* Reset the query buffer as though for \r */ resetPQExpBuffer(query_buf); @@ -5047,7 +5069,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) +do_watch(PQExpBuffer query_buf, double sleep, int iter) { long sleep_ms = (long) (sleep * 1000); printQueryOpt myopt = pset.popt; @@ -5149,7 +5171,7 @@ do_watch(PQExpBuffer query_buf, double sleep) title_len = (user_title ? strlen(user_title) : 0) + 256; title = pg_malloc(title_len); - for (;;) + for (int i = 1;;) { time_t timer; char timebuf[128]; @@ -5244,6 +5266,11 @@ do_watch(PQExpBuffer query_buf, double sleep) if (done) break; #endif + /* If we have iteration count - check that it's not exceeded yet */ + if (iter && (i++ == iter)) + { + break; + } } if (pagerpipe) diff --git a/src/bin/psql/help.c b/src/bin/psql/help.c index e45c4aaca5..9561f15a71 100644 --- a/src/bin/psql/help.c +++ b/src/bin/psql/help.c @@ -200,7 +200,7 @@ slashUsage(unsigned short int pager) HELP0(" \\gset [PREFIX] execute query and store result in psql variables\n"); HELP0(" \\gx [(OPTIONS)] [FILE] as \\g, but forces expanded output mode\n"); HELP0(" \\q quit psql\n"); - HELP0(" \\watch [SEC] execute query every SEC seconds\n"); + HELP0(" \\watch [SEC [N]] execute query every SEC seconds N times\n"); HELP0("\n"); HELP0("Help\n"); diff --git a/src/test/regress/expected/psql.out b/src/test/regress/expected/psql.out index 8fc62cebd2..e5d7e4c4f5 100644 --- a/src/test/regress/expected/psql.out +++ b/src/test/regress/expected/psql.out @@ -4536,7 +4536,7 @@ invalid command \lo \timing arg1 \unset arg1 \w arg1 - \watch arg1 + \watch arg1 arg2 \x arg1 -- \else here is eaten as part of OT_FILEPIPE argument \w |/no/such/file \else diff --git a/src/test/regress/sql/psql.sql b/src/test/regress/sql/psql.sql index 2da9665a19..661847a2f1 100644 --- a/src/test/regress/sql/psql.sql +++ b/src/test/regress/sql/psql.sql @@ -1022,7 +1022,7 @@ select \if false \\ (bogus \else \\ 42 \endif \\ forty_two; \timing arg1 \unset arg1 \w arg1 - \watch arg1 + \watch arg1 arg2 \x arg1 -- \else here is eaten as part of OT_FILEPIPE argument \w |/no/such/file \else -- 2.32.0 (Apple Git-132)