aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/utils/misc/guc.c52
1 files changed, 31 insertions, 21 deletions
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 3c695c16153..da74f00ab24 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -8903,7 +8903,9 @@ can_skip_gucvar(struct config_generic * gconf)
/*
* estimate_variable_size:
- * Estimate max size for dumping the given GUC variable.
+ * Compute space needed for dumping the given GUC variable.
+ *
+ * It's OK to overestimate, but not to underestimate.
*/
static Size
estimate_variable_size(struct config_generic * gconf)
@@ -8914,9 +8916,8 @@ estimate_variable_size(struct config_generic * gconf)
if (can_skip_gucvar(gconf))
return 0;
- size = 0;
-
- size = add_size(size, strlen(gconf->name) + 1);
+ /* Name, plus trailing zero byte. */
+ size = strlen(gconf->name) + 1;
/* Get the maximum display length of the GUC value. */
switch (gconf->vartype)
@@ -8937,7 +8938,7 @@ estimate_variable_size(struct config_generic * gconf)
* small values. Maximum value is 2147483647, i.e. 10 chars.
* Include one byte for sign.
*/
- if (abs(*conf->variable) < 1000)
+ if (Abs(*conf->variable) < 1000)
valsize = 3 + 1;
else
valsize = 10 + 1;
@@ -8947,11 +8948,12 @@ estimate_variable_size(struct config_generic * gconf)
case PGC_REAL:
{
/*
- * We are going to print it with %.17g. Account for sign,
- * decimal point, and e+nnn notation. E.g.
- * -3.9932904234000002e+110
+ * We are going to print it with %e with REALTYPE_PRECISION
+ * fractional digits. Account for sign, leading digit,
+ * decimal point, and exponent with up to 3 digits. E.g.
+ * -3.99329042340000021e+110
*/
- valsize = REALTYPE_PRECISION + 1 + 1 + 5;
+ valsize = 1 + 1 + 1 + REALTYPE_PRECISION + 5;
}
break;
@@ -8959,7 +8961,15 @@ estimate_variable_size(struct config_generic * gconf)
{
struct config_string *conf = (struct config_string *) gconf;
- valsize = strlen(*conf->variable);
+ /*
+ * If the value is NULL, we transmit it as an empty string.
+ * Although this is not physically the same value, GUC
+ * generally treats a NULL the same as empty string.
+ */
+ if (*conf->variable)
+ valsize = strlen(*conf->variable);
+ else
+ valsize = 0;
}
break;
@@ -8972,17 +8982,17 @@ estimate_variable_size(struct config_generic * gconf)
break;
}
- /* Allow space for terminating zero-byte */
+ /* Allow space for terminating zero-byte for value */
size = add_size(size, valsize + 1);
if (gconf->sourcefile)
size = add_size(size, strlen(gconf->sourcefile));
- /* Allow space for terminating zero-byte */
+ /* Allow space for terminating zero-byte for sourcefile */
size = add_size(size, 1);
- /* Include line whenever we include file. */
- if (gconf->sourcefile)
+ /* Include line whenever file is nonempty. */
+ if (gconf->sourcefile && gconf->sourcefile[0])
size = add_size(size, sizeof(gconf->sourceline));
size = add_size(size, sizeof(gconf->source));
@@ -9100,7 +9110,7 @@ serialize_variable(char **destptr, Size *maxbytes,
{
struct config_real *conf = (struct config_real *) gconf;
- do_serialize(destptr, maxbytes, "%.*g",
+ do_serialize(destptr, maxbytes, "%.*e",
REALTYPE_PRECISION, *conf->variable);
}
break;
@@ -9109,7 +9119,9 @@ serialize_variable(char **destptr, Size *maxbytes,
{
struct config_string *conf = (struct config_string *) gconf;
- do_serialize(destptr, maxbytes, "%s", *conf->variable);
+ /* NULL becomes empty string, see estimate_variable_size() */
+ do_serialize(destptr, maxbytes, "%s",
+ *conf->variable ? *conf->variable : "");
}
break;
@@ -9126,7 +9138,7 @@ serialize_variable(char **destptr, Size *maxbytes,
do_serialize(destptr, maxbytes, "%s",
(gconf->sourcefile ? gconf->sourcefile : ""));
- if (gconf->sourcefile)
+ if (gconf->sourcefile && gconf->sourcefile[0])
do_serialize_binary(destptr, maxbytes, &gconf->sourceline,
sizeof(gconf->sourceline));
@@ -9193,7 +9205,7 @@ read_gucstate(char **srcptr, char *srcend)
for (ptr = *srcptr; ptr < srcend && *ptr != '\0'; ptr++)
;
- if (ptr > srcend)
+ if (ptr >= srcend)
elog(ERROR, "could not find null terminator in GUC state");
/* Set the new position to the byte following the terminating NUL */
@@ -9247,9 +9259,7 @@ RestoreGUCState(void *gucstate)
{
int result;
- if ((varname = read_gucstate(&srcptr, srcend)) == NULL)
- break;
-
+ varname = read_gucstate(&srcptr, srcend);
varvalue = read_gucstate(&srcptr, srcend);
varsourcefile = read_gucstate(&srcptr, srcend);
if (varsourcefile[0])