Skip to content

Commit 8681d01

Browse files
author
Commitfest Bot
committed
[CF 5353] v8 - Allow default \watch interval in psql to be configured
This branch was automatically generated by a robot using patches from an email thread registered at: https://commitfest.postgresql.org//5353 The branch will be overwritten each time a new version is posted to the thread, and also periodically to check for bitrot caused by changes on the master branch. (es): https://www.postgresql.org/message-id/[email protected] Author(s): Daniel Gustafsson
2 parents 19c6eb0 + ab5ca62 commit 8681d01

File tree

8 files changed

+141
-2
lines changed

8 files changed

+141
-2
lines changed

‎doc/src/sgml/ref/psql-ref.sgml

+13
Original file line numberDiff line numberDiff line change
@@ -3852,6 +3852,8 @@ SELECT 1 \bind \sendpipeline
38523852
until interrupted, or the query fails, or the execution count limit
38533853
(if given) is reached, or the query no longer returns the minimum number
38543854
of rows. Wait the specified number of seconds (default 2) between executions.
3855+
The default wait can be changed with the variable
3856+
<xref linkend="app-psql-variables-watch-interval"/>).
38553857
For backwards compatibility,
38563858
<replaceable class="parameter">seconds</replaceable> can be specified
38573859
with or without an <literal>interval=</literal> prefix.
@@ -4746,6 +4748,17 @@ bar
47464748
</listitem>
47474749
</varlistentry>
47484750

4751+
<varlistentry id="app-psql-variables-watch-interval">
4752+
<term><varname>WATCH_INTERVAL</varname></term>
4753+
<listitem>
4754+
<para>
4755+
This variable sets the default interval which <command>\watch</command>
4756+
waits between executing the query. Specifying an interval in the
4757+
command overrides this variable.
4758+
</para>
4759+
</listitem>
4760+
</varlistentry>
4761+
47494762
</variablelist>
47504763

47514764
</refsect3>

‎src/bin/psql/command.c

+4-2
Original file line numberDiff line numberDiff line change
@@ -3278,7 +3278,7 @@ exec_command_watch(PsqlScanState scan_state, bool active_branch,
32783278
bool have_sleep = false;
32793279
bool have_iter = false;
32803280
bool have_min_rows = false;
3281-
double sleep = 2;
3281+
double sleep = pset.watch_interval;
32823282
int iter = 0;
32833283
int min_rows = 0;
32843284

@@ -3292,7 +3292,9 @@ exec_command_watch(PsqlScanState scan_state, bool active_branch,
32923292
/*
32933293
* Parse arguments. We allow either an unlabeled interval or
32943294
* "name=value", where name is from the set ('i', 'interval', 'c',
3295-
* 'count', 'm', 'min_rows').
3295+
* 'count', 'm', 'min_rows'). The parsing of interval value should
3296+
* be kept in sync with ParseVariableDouble which is used for setting
3297+
* the default interval value.
32963298
*/
32973299
while (success)
32983300
{

‎src/bin/psql/help.c

+2
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,8 @@ helpVariables(unsigned short int pager)
460460
" VERSION_NAME\n"
461461
" VERSION_NUM\n"
462462
" psql's version (in verbose string, short string, or numeric format)\n");
463+
HELP0(" WATCH_INTERVAL\n"
464+
" number of seconds \\watch by default waits between executing the query buffer\n");
463465

464466
HELP0("\nDisplay settings:\n");
465467
HELP0("Usage:\n");

‎src/bin/psql/settings.h

+7
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@
2727
#define DEFAULT_PROMPT2 "%/%R%x%# "
2828
#define DEFAULT_PROMPT3 ">> "
2929

30+
#define DEFAULT_WATCH_INTERVAL "2"
31+
/*
32+
* Limit the max default setting to a value which should be safe for the
33+
* itimer call, yet large enough to cover all realistic usecases.
34+
*/
35+
#define DEFAULT_WATCH_INTERVAL_MAX (1000*1000)
3036
/*
3137
* Note: these enums should generally be chosen so that zero corresponds
3238
* to the default behavior.
@@ -166,6 +172,7 @@ typedef struct _psqlSettings
166172
int fetch_count;
167173
int histsize;
168174
int ignoreeof;
175+
double watch_interval;
169176
PSQL_ECHO echo;
170177
PSQL_ECHO_HIDDEN echo_hidden;
171178
PSQL_ERROR_ROLLBACK on_error_rollback;

‎src/bin/psql/startup.c

+18
Original file line numberDiff line numberDiff line change
@@ -944,6 +944,21 @@ histsize_hook(const char *newval)
944944
return ParseVariableNum(newval, "HISTSIZE", &pset.histsize);
945945
}
946946

947+
static char *
948+
watch_interval_substitute_hook(char *newval)
949+
{
950+
if (newval == NULL)
951+
newval = pg_strdup(DEFAULT_WATCH_INTERVAL);
952+
return newval;
953+
}
954+
955+
static bool
956+
watch_interval_hook(const char *newval)
957+
{
958+
return ParseVariableDouble(newval, "WATCH_INTERVAL", &pset.watch_interval,
959+
0, DEFAULT_WATCH_INTERVAL_MAX);
960+
}
961+
947962
static char *
948963
ignoreeof_substitute_hook(char *newval)
949964
{
@@ -1270,4 +1285,7 @@ EstablishVariableSpace(void)
12701285
SetVariableHooks(pset.vars, "HIDE_TABLEAM",
12711286
bool_substitute_hook,
12721287
hide_tableam_hook);
1288+
SetVariableHooks(pset.vars, "WATCH_INTERVAL",
1289+
watch_interval_substitute_hook,
1290+
watch_interval_hook);
12731291
}

‎src/bin/psql/t/001_basic.pl

+24
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,12 @@ sub psql_fails_like
375375
$node, sprintf('SELECT 1 \watch c=3 i=%g', 0.0001),
376376
qr/1\n1\n1/, '\watch with 3 iterations, interval of 0.0001');
377377

378+
# Test zero interval
379+
psql_like(
380+
$node, '\set WATCH_INTERVAL 0
381+
SELECT 1 \watch c=3',
382+
qr/1\n1\n1/, '\watch with 3 iterations, interval of 0');
383+
378384
# Check \watch minimum row count
379385
psql_fails_like(
380386
$node,
@@ -426,6 +432,24 @@ sub psql_fails_like
426432
qr/iteration count is specified more than once/,
427433
'\watch, iteration count is specified more than once');
428434

435+
# Check WATCH_INTERVAL
436+
psql_like(
437+
$node,
438+
'\echo :WATCH_INTERVAL
439+
\set WATCH_INTERVAL 0.001
440+
\echo :WATCH_INTERVAL
441+
\unset WATCH_INTERVAL
442+
\echo :WATCH_INTERVAL',
443+
qr/^2$
444+
^0.001$
445+
^2$/m,
446+
'WATCH_INTERVAL variable is set and updated');
447+
psql_fails_like(
448+
$node,
449+
'\set WATCH_INTERVAL 1e500',
450+
qr/is out of range/,
451+
'WATCH_INTERVAL variable is out of range');
452+
429453
# Test \g output piped into a program.
430454
# The program is perl -pe '' to simply copy the input to the output.
431455
my $g_file = "$tempdir/g_file_1.out";

‎src/bin/psql/variables.c

+70
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
*/
88
#include "postgres_fe.h"
99

10+
#include <math.h>
11+
1012
#include "common.h"
1113
#include "common/logging.h"
1214
#include "variables.h"
@@ -179,6 +181,74 @@ ParseVariableNum(const char *value, const char *name, int *result)
179181
}
180182
}
181183

184+
/*
185+
* Try to interpret "value" as a double value, and if successful store it in
186+
* *result. If unsuccessful, *result isn't clobbered. "name" is the variable
187+
* which is being assigned, the value of which is only used to produce a good
188+
* error message. Pass NULL as the name to suppress the error message. The
189+
* value must be within the range [min,max] in order to be considered valid.
190+
*
191+
* Returns true, with *result containing the interpreted value, if "value" is
192+
* syntactically valid, else false (with *result unchanged).
193+
*/
194+
bool
195+
ParseVariableDouble(const char *value, const char *name, double *result, double min, double max)
196+
{
197+
char *end;
198+
double dblval;
199+
200+
/*
201+
* Empty-string input has historically been treated differently by strtod
202+
* on various platforms, so handle that by specifically checking for it.
203+
*/
204+
if ((value == NULL) || (*value == '\0'))
205+
{
206+
if (name)
207+
pg_log_error("invalid input syntax for \"%s\"", name);
208+
return false;
209+
}
210+
211+
errno = 0;
212+
dblval = strtod(value, &end);
213+
if (errno == 0 && *end == '\0' && end != value)
214+
{
215+
if (dblval < min)
216+
{
217+
if (name)
218+
pg_log_error("invalid value \"%s\" for \"%s\": must be greater than %.2f",
219+
value, name, min);
220+
return false;
221+
}
222+
else if (dblval > max)
223+
{
224+
if (name)
225+
pg_log_error("invalid value \"%s\" for \"%s\": must be less than %.2f",
226+
value, name, max);
227+
}
228+
*result = dblval;
229+
return true;
230+
}
231+
232+
/*
233+
* Cater for platforms which treat values which aren't zero, but that are
234+
* too close to zero to have full precision, by checking for zero or real
235+
* out-of-range values.
236+
*/
237+
else if ((errno = ERANGE) &&
238+
(dblval == 0.0 || dblval >= HUGE_VAL || dblval <= -HUGE_VAL))
239+
{
240+
if (name)
241+
pg_log_error("\"%s\" is out of range for \"%s\"", value, name);
242+
return false;
243+
}
244+
else
245+
{
246+
if (name)
247+
pg_log_error("invalid value \"%s\" for \"%s\"", value, name);
248+
return false;
249+
}
250+
}
251+
182252
/*
183253
* Print values of all variables.
184254
*/

‎src/bin/psql/variables.h

+3
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,9 @@ bool ParseVariableBool(const char *value, const char *name,
8181
bool ParseVariableNum(const char *value, const char *name,
8282
int *result);
8383

84+
bool ParseVariableDouble(const char *value, const char *name,
85+
double *result, double min, double max);
86+
8487
void PrintVariables(VariableSpace space);
8588

8689
bool SetVariable(VariableSpace space, const char *name, const char *value);

0 commit comments

Comments
 (0)