mirror of
https://github.com/postgres/postgres.git
synced 2025-04-20 00:42:27 +03:00
psql: Make default \watch interval configurable
The default interval for \watch to wait between executing queries, when executed without a specified interval, was hardcoded to two seconds. This adds the new variable WATCH_INTERVAL which is used to set the default interval, making it configurable for the user. This makes \watch the first command which has a user configurable default setting. Author: Daniel Gustafsson <daniel@yesql.se> Reviewed-by: Heikki Linnakangas <hlinnaka@iki.fi> Reviewed-by: Michael Paquier <michael@paquier.xyz> Reviewed-by: Kirill Reshke <reshkekirill@gmail.com> Reviewed-by: Masahiro Ikeda <ikedamsh@oss.nttdata.com> Reviewed-by: Laurenz Albe <laurenz.albe@cybertec.at> Reviewed-by: Greg Sabino Mullane <htamfids@gmail.com> Reviewed-by: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com> Discussion: https://postgr.es/m/B2FD26B4-8F64-4552-A603-5CC3DF1C7103@yesql.se
This commit is contained in:
parent
a19db08274
commit
1a759c8327
@ -3852,6 +3852,8 @@ SELECT 1 \bind \sendpipeline
|
|||||||
until interrupted, or the query fails, or the execution count limit
|
until interrupted, or the query fails, or the execution count limit
|
||||||
(if given) is reached, or the query no longer returns the minimum number
|
(if given) is reached, or the query no longer returns the minimum number
|
||||||
of rows. Wait the specified number of seconds (default 2) between executions.
|
of rows. Wait the specified number of seconds (default 2) between executions.
|
||||||
|
The default wait can be changed with the variable
|
||||||
|
<xref linkend="app-psql-variables-watch-interval"/>).
|
||||||
For backwards compatibility,
|
For backwards compatibility,
|
||||||
<replaceable class="parameter">seconds</replaceable> can be specified
|
<replaceable class="parameter">seconds</replaceable> can be specified
|
||||||
with or without an <literal>interval=</literal> prefix.
|
with or without an <literal>interval=</literal> prefix.
|
||||||
@ -4746,6 +4748,17 @@ bar
|
|||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry id="app-psql-variables-watch-interval">
|
||||||
|
<term><varname>WATCH_INTERVAL</varname></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
This variable sets the default interval which <command>\watch</command>
|
||||||
|
waits between executing the query. Specifying an interval in the
|
||||||
|
command overrides this variable.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
</variablelist>
|
</variablelist>
|
||||||
|
|
||||||
</refsect3>
|
</refsect3>
|
||||||
|
@ -3278,7 +3278,7 @@ exec_command_watch(PsqlScanState scan_state, bool active_branch,
|
|||||||
bool have_sleep = false;
|
bool have_sleep = false;
|
||||||
bool have_iter = false;
|
bool have_iter = false;
|
||||||
bool have_min_rows = false;
|
bool have_min_rows = false;
|
||||||
double sleep = 2;
|
double sleep = pset.watch_interval;
|
||||||
int iter = 0;
|
int iter = 0;
|
||||||
int min_rows = 0;
|
int min_rows = 0;
|
||||||
|
|
||||||
@ -3292,7 +3292,9 @@ exec_command_watch(PsqlScanState scan_state, bool active_branch,
|
|||||||
/*
|
/*
|
||||||
* Parse arguments. We allow either an unlabeled interval or
|
* Parse arguments. We allow either an unlabeled interval or
|
||||||
* "name=value", where name is from the set ('i', 'interval', 'c',
|
* "name=value", where name is from the set ('i', 'interval', 'c',
|
||||||
* 'count', 'm', 'min_rows').
|
* 'count', 'm', 'min_rows'). The parsing of interval value should be
|
||||||
|
* kept in sync with ParseVariableDouble which is used for setting the
|
||||||
|
* default interval value.
|
||||||
*/
|
*/
|
||||||
while (success)
|
while (success)
|
||||||
{
|
{
|
||||||
|
@ -460,6 +460,8 @@ helpVariables(unsigned short int pager)
|
|||||||
" VERSION_NAME\n"
|
" VERSION_NAME\n"
|
||||||
" VERSION_NUM\n"
|
" VERSION_NUM\n"
|
||||||
" psql's version (in verbose string, short string, or numeric format)\n");
|
" psql's version (in verbose string, short string, or numeric format)\n");
|
||||||
|
HELP0(" WATCH_INTERVAL\n"
|
||||||
|
" number of seconds \\watch by default waits between executing the query buffer\n");
|
||||||
|
|
||||||
HELP0("\nDisplay settings:\n");
|
HELP0("\nDisplay settings:\n");
|
||||||
HELP0("Usage:\n");
|
HELP0("Usage:\n");
|
||||||
|
@ -27,6 +27,12 @@
|
|||||||
#define DEFAULT_PROMPT2 "%/%R%x%# "
|
#define DEFAULT_PROMPT2 "%/%R%x%# "
|
||||||
#define DEFAULT_PROMPT3 ">> "
|
#define DEFAULT_PROMPT3 ">> "
|
||||||
|
|
||||||
|
#define DEFAULT_WATCH_INTERVAL "2"
|
||||||
|
/*
|
||||||
|
* Limit the max default setting to a value which should be safe for the
|
||||||
|
* itimer call, yet large enough to cover all realistic usecases.
|
||||||
|
*/
|
||||||
|
#define DEFAULT_WATCH_INTERVAL_MAX (1000*1000)
|
||||||
/*
|
/*
|
||||||
* Note: these enums should generally be chosen so that zero corresponds
|
* Note: these enums should generally be chosen so that zero corresponds
|
||||||
* to the default behavior.
|
* to the default behavior.
|
||||||
@ -166,6 +172,7 @@ typedef struct _psqlSettings
|
|||||||
int fetch_count;
|
int fetch_count;
|
||||||
int histsize;
|
int histsize;
|
||||||
int ignoreeof;
|
int ignoreeof;
|
||||||
|
double watch_interval;
|
||||||
PSQL_ECHO echo;
|
PSQL_ECHO echo;
|
||||||
PSQL_ECHO_HIDDEN echo_hidden;
|
PSQL_ECHO_HIDDEN echo_hidden;
|
||||||
PSQL_ERROR_ROLLBACK on_error_rollback;
|
PSQL_ERROR_ROLLBACK on_error_rollback;
|
||||||
|
@ -944,6 +944,21 @@ histsize_hook(const char *newval)
|
|||||||
return ParseVariableNum(newval, "HISTSIZE", &pset.histsize);
|
return ParseVariableNum(newval, "HISTSIZE", &pset.histsize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
watch_interval_substitute_hook(char *newval)
|
||||||
|
{
|
||||||
|
if (newval == NULL)
|
||||||
|
newval = pg_strdup(DEFAULT_WATCH_INTERVAL);
|
||||||
|
return newval;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
watch_interval_hook(const char *newval)
|
||||||
|
{
|
||||||
|
return ParseVariableDouble(newval, "WATCH_INTERVAL", &pset.watch_interval,
|
||||||
|
0, DEFAULT_WATCH_INTERVAL_MAX);
|
||||||
|
}
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
ignoreeof_substitute_hook(char *newval)
|
ignoreeof_substitute_hook(char *newval)
|
||||||
{
|
{
|
||||||
@ -1270,4 +1285,7 @@ EstablishVariableSpace(void)
|
|||||||
SetVariableHooks(pset.vars, "HIDE_TABLEAM",
|
SetVariableHooks(pset.vars, "HIDE_TABLEAM",
|
||||||
bool_substitute_hook,
|
bool_substitute_hook,
|
||||||
hide_tableam_hook);
|
hide_tableam_hook);
|
||||||
|
SetVariableHooks(pset.vars, "WATCH_INTERVAL",
|
||||||
|
watch_interval_substitute_hook,
|
||||||
|
watch_interval_hook);
|
||||||
}
|
}
|
||||||
|
@ -375,6 +375,12 @@ psql_like(
|
|||||||
$node, sprintf('SELECT 1 \watch c=3 i=%g', 0.0001),
|
$node, sprintf('SELECT 1 \watch c=3 i=%g', 0.0001),
|
||||||
qr/1\n1\n1/, '\watch with 3 iterations, interval of 0.0001');
|
qr/1\n1\n1/, '\watch with 3 iterations, interval of 0.0001');
|
||||||
|
|
||||||
|
# Test zero interval
|
||||||
|
psql_like(
|
||||||
|
$node, '\set WATCH_INTERVAL 0
|
||||||
|
SELECT 1 \watch c=3',
|
||||||
|
qr/1\n1\n1/, '\watch with 3 iterations, interval of 0');
|
||||||
|
|
||||||
# Check \watch minimum row count
|
# Check \watch minimum row count
|
||||||
psql_fails_like(
|
psql_fails_like(
|
||||||
$node,
|
$node,
|
||||||
@ -426,6 +432,24 @@ psql_fails_like(
|
|||||||
qr/iteration count is specified more than once/,
|
qr/iteration count is specified more than once/,
|
||||||
'\watch, iteration count is specified more than once');
|
'\watch, iteration count is specified more than once');
|
||||||
|
|
||||||
|
# Check WATCH_INTERVAL
|
||||||
|
psql_like(
|
||||||
|
$node,
|
||||||
|
'\echo :WATCH_INTERVAL
|
||||||
|
\set WATCH_INTERVAL 0.001
|
||||||
|
\echo :WATCH_INTERVAL
|
||||||
|
\unset WATCH_INTERVAL
|
||||||
|
\echo :WATCH_INTERVAL',
|
||||||
|
qr/^2$
|
||||||
|
^0.001$
|
||||||
|
^2$/m,
|
||||||
|
'WATCH_INTERVAL variable is set and updated');
|
||||||
|
psql_fails_like(
|
||||||
|
$node,
|
||||||
|
'\set WATCH_INTERVAL 1e500',
|
||||||
|
qr/is out of range/,
|
||||||
|
'WATCH_INTERVAL variable is out of range');
|
||||||
|
|
||||||
# Test \g output piped into a program.
|
# Test \g output piped into a program.
|
||||||
# The program is perl -pe '' to simply copy the input to the output.
|
# The program is perl -pe '' to simply copy the input to the output.
|
||||||
my $g_file = "$tempdir/g_file_1.out";
|
my $g_file = "$tempdir/g_file_1.out";
|
||||||
|
@ -7,6 +7,8 @@
|
|||||||
*/
|
*/
|
||||||
#include "postgres_fe.h"
|
#include "postgres_fe.h"
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "common/logging.h"
|
#include "common/logging.h"
|
||||||
#include "variables.h"
|
#include "variables.h"
|
||||||
@ -179,6 +181,74 @@ ParseVariableNum(const char *value, const char *name, int *result)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Try to interpret "value" as a double value, and if successful store it in
|
||||||
|
* *result. If unsuccessful, *result isn't clobbered. "name" is the variable
|
||||||
|
* which is being assigned, the value of which is only used to produce a good
|
||||||
|
* error message. Pass NULL as the name to suppress the error message. The
|
||||||
|
* value must be within the range [min,max] in order to be considered valid.
|
||||||
|
*
|
||||||
|
* Returns true, with *result containing the interpreted value, if "value" is
|
||||||
|
* syntactically valid, else false (with *result unchanged).
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
ParseVariableDouble(const char *value, const char *name, double *result, double min, double max)
|
||||||
|
{
|
||||||
|
char *end;
|
||||||
|
double dblval;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Empty-string input has historically been treated differently by strtod
|
||||||
|
* on various platforms, so handle that by specifically checking for it.
|
||||||
|
*/
|
||||||
|
if ((value == NULL) || (*value == '\0'))
|
||||||
|
{
|
||||||
|
if (name)
|
||||||
|
pg_log_error("invalid input syntax for \"%s\"", name);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
dblval = strtod(value, &end);
|
||||||
|
if (errno == 0 && *end == '\0' && end != value)
|
||||||
|
{
|
||||||
|
if (dblval < min)
|
||||||
|
{
|
||||||
|
if (name)
|
||||||
|
pg_log_error("invalid value \"%s\" for \"%s\": must be greater than %.2f",
|
||||||
|
value, name, min);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (dblval > max)
|
||||||
|
{
|
||||||
|
if (name)
|
||||||
|
pg_log_error("invalid value \"%s\" for \"%s\": must be less than %.2f",
|
||||||
|
value, name, max);
|
||||||
|
}
|
||||||
|
*result = dblval;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Cater for platforms which treat values which aren't zero, but that are
|
||||||
|
* too close to zero to have full precision, by checking for zero or real
|
||||||
|
* out-of-range values.
|
||||||
|
*/
|
||||||
|
else if ((errno = ERANGE) &&
|
||||||
|
(dblval == 0.0 || dblval >= HUGE_VAL || dblval <= -HUGE_VAL))
|
||||||
|
{
|
||||||
|
if (name)
|
||||||
|
pg_log_error("\"%s\" is out of range for \"%s\"", value, name);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (name)
|
||||||
|
pg_log_error("invalid value \"%s\" for \"%s\"", value, name);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Print values of all variables.
|
* Print values of all variables.
|
||||||
*/
|
*/
|
||||||
|
@ -81,6 +81,9 @@ bool ParseVariableBool(const char *value, const char *name,
|
|||||||
bool ParseVariableNum(const char *value, const char *name,
|
bool ParseVariableNum(const char *value, const char *name,
|
||||||
int *result);
|
int *result);
|
||||||
|
|
||||||
|
bool ParseVariableDouble(const char *value, const char *name,
|
||||||
|
double *result, double min, double max);
|
||||||
|
|
||||||
void PrintVariables(VariableSpace space);
|
void PrintVariables(VariableSpace space);
|
||||||
|
|
||||||
bool SetVariable(VariableSpace space, const char *name, const char *value);
|
bool SetVariable(VariableSpace space, const char *name, const char *value);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user