aboutsummaryrefslogtreecommitdiff
path: root/src/bin/psql/variables.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/bin/psql/variables.c')
-rw-r--r--src/bin/psql/variables.c70
1 files changed, 70 insertions, 0 deletions
diff --git a/src/bin/psql/variables.c b/src/bin/psql/variables.c
index 59956028918..5150eb0532b 100644
--- a/src/bin/psql/variables.c
+++ b/src/bin/psql/variables.c
@@ -7,6 +7,8 @@
*/
#include "postgres_fe.h"
+#include <math.h>
+
#include "common.h"
#include "common/logging.h"
#include "variables.h"
@@ -180,6 +182,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.
*/
void