LCOV - differential code coverage report
Current view: top level - src/bin/psql - variables.c (source / functions) Coverage Total Hit UBC CBC
Current: c70b6db34ffeab48beef1fb4ce61bcad3772b8dd vs 06473f5a344df8c9594ead90a609b86f6724cff8 Lines: 80.7 % 187 151 36 151
Current Date: 2025-09-06 07:49:51 +0900 Functions: 84.6 % 13 11 2 11
Baseline: lcov-20250906-005545-baseline Branches: 63.8 % 160 102 58 102
Baseline Date: 2025-09-05 08:21:35 +0100 Line coverage date bins:
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
(30,360] days: 56.0 % 25 14 11 14
(360..) days: 84.6 % 162 137 25 137
Function coverage date bins:
(30,360] days: 100.0 % 1 1 1
(360..) days: 83.3 % 12 10 2 10
Branch coverage date bins:
(30,360] days: 37.5 % 32 12 20 12
(360..) days: 70.3 % 128 90 38 90

 Age         Owner                    Branch data    TLA  Line data    Source code
                                  1                 :                : /*
                                  2                 :                :  * psql - the PostgreSQL interactive terminal
                                  3                 :                :  *
                                  4                 :                :  * Copyright (c) 2000-2025, PostgreSQL Global Development Group
                                  5                 :                :  *
                                  6                 :                :  * src/bin/psql/variables.c
                                  7                 :                :  */
                                  8                 :                : #include "postgres_fe.h"
                                  9                 :                : 
                                 10                 :                : #include <math.h>
                                 11                 :                : 
                                 12                 :                : #include "common.h"
                                 13                 :                : #include "common/logging.h"
                                 14                 :                : #include "variables.h"
                                 15                 :                : 
                                 16                 :                : /*
                                 17                 :                :  * Check whether a variable's name is allowed.
                                 18                 :                :  *
                                 19                 :                :  * We allow any non-ASCII character, as well as ASCII letters, digits, and
                                 20                 :                :  * underscore.  Keep this in sync with the definition of variable_char in
                                 21                 :                :  * psqlscan.l and psqlscanslash.l.
                                 22                 :                :  */
                                 23                 :                : static bool
 5125 tgl@sss.pgh.pa.us          24                 :CBC     1559058 : valid_variable_name(const char *name)
                                 25                 :                : {
                                 26                 :        1559058 :     const unsigned char *ptr = (const unsigned char *) name;
                                 27                 :                : 
                                 28                 :                :     /* Mustn't be zero-length */
                                 29         [ -  + ]:        1559058 :     if (*ptr == '\0')
 5125 tgl@sss.pgh.pa.us          30                 :UBC           0 :         return false;
                                 31                 :                : 
 5125 tgl@sss.pgh.pa.us          32         [ +  + ]:CBC    21873717 :     while (*ptr)
                                 33                 :                :     {
                                 34         [ +  - ]:       20314665 :         if (IS_HIGHBIT_SET(*ptr) ||
                                 35                 :       20314665 :             strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz"
                                 36         [ +  + ]:       20314665 :                    "_0123456789", *ptr) != NULL)
                                 37                 :       20314659 :             ptr++;
                                 38                 :                :         else
                                 39                 :              6 :             return false;
                                 40                 :                :     }
                                 41                 :                : 
                                 42                 :        1559052 :     return true;
                                 43                 :                : }
                                 44                 :                : 
                                 45                 :                : /*
                                 46                 :                :  * A "variable space" is represented by an otherwise-unused struct _variable
                                 47                 :                :  * that serves as list header.
                                 48                 :                :  *
                                 49                 :                :  * The list entries are kept in name order (according to strcmp).  This
                                 50                 :                :  * is mainly to make the output of PrintVariables() more pleasing.
                                 51                 :                :  */
                                 52                 :                : VariableSpace
 9438 bruce@momjian.us           53                 :           8485 : CreateVariableSpace(void)
                                 54                 :                : {
                                 55                 :                :     struct _variable *ptr;
                                 56                 :                : 
 6948 tgl@sss.pgh.pa.us          57                 :           8485 :     ptr = pg_malloc(sizeof *ptr);
                                 58                 :           8485 :     ptr->name = NULL;
                                 59                 :           8485 :     ptr->value = NULL;
 3139                            60                 :           8485 :     ptr->substitute_hook = NULL;
 6948                            61                 :           8485 :     ptr->assign_hook = NULL;
                                 62                 :           8485 :     ptr->next = NULL;
                                 63                 :                : 
 9438 bruce@momjian.us           64                 :           8485 :     return ptr;
                                 65                 :                : }
                                 66                 :                : 
                                 67                 :                : /*
                                 68                 :                :  * Get string value of variable, or NULL if it's not defined.
                                 69                 :                :  *
                                 70                 :                :  * Note: result is valid until variable is next assigned to.
                                 71                 :                :  */
                                 72                 :                : const char *
                                 73                 :           1920 : GetVariable(VariableSpace space, const char *name)
                                 74                 :                : {
                                 75                 :                :     struct _variable *current;
                                 76                 :                : 
                                 77         [ -  + ]:           1920 :     if (!space)
 9438 bruce@momjian.us           78                 :UBC           0 :         return NULL;
                                 79                 :                : 
 7017 tgl@sss.pgh.pa.us          80         [ +  + ]:CBC       73618 :     for (current = space->next; current; current = current->next)
                                 81                 :                :     {
 3139                            82                 :          73617 :         int         cmp = strcmp(current->name, name);
                                 83                 :                : 
                                 84         [ +  + ]:          73617 :         if (cmp == 0)
                                 85                 :                :         {
                                 86                 :                :             /* this is correct answer when value is NULL, too */
 9438 bruce@momjian.us           87                 :           1679 :             return current->value;
                                 88                 :                :         }
 3139 tgl@sss.pgh.pa.us          89         [ +  + ]:          71938 :         if (cmp > 0)
                                 90                 :            240 :             break;              /* it's not there */
                                 91                 :                :     }
                                 92                 :                : 
 9438 bruce@momjian.us           93                 :            241 :     return NULL;
                                 94                 :                : }
                                 95                 :                : 
                                 96                 :                : /*
                                 97                 :                :  * Try to interpret "value" as a boolean value, and if successful,
                                 98                 :                :  * store it in *result.  Otherwise don't clobber *result.
                                 99                 :                :  *
                                100                 :                :  * Valid values are: true, false, yes, no, on, off, 1, 0; as well as unique
                                101                 :                :  * prefixes thereof.
                                102                 :                :  *
                                103                 :                :  * "name" is the name of the variable we're assigning to, to use in error
                                104                 :                :  * report if any.  Pass name == NULL to suppress the error report.
                                105                 :                :  *
                                106                 :                :  * Return true when "value" is syntactically valid, false otherwise.
                                107                 :                :  */
                                108                 :                : bool
 3141 tgl@sss.pgh.pa.us         109                 :         117118 : ParseVariableBool(const char *value, const char *name, bool *result)
                                110                 :                : {
                                111                 :                :     size_t      len;
                                112                 :         117118 :     bool        valid = true;
                                113                 :                : 
                                114                 :                :     /* Treat "unset" as an empty string, which will lead to error below */
 6331 bruce@momjian.us          115         [ -  + ]:         117118 :     if (value == NULL)
 3139 tgl@sss.pgh.pa.us         116                 :UBC           0 :         value = "";
                                117                 :                : 
 6331 bruce@momjian.us          118                 :CBC      117118 :     len = strlen(value);
                                119                 :                : 
 3141 tgl@sss.pgh.pa.us         120   [ +  -  +  + ]:         117118 :     if (len > 0 && pg_strncasecmp(value, "true", len) == 0)
                                121                 :            111 :         *result = true;
                                122   [ +  -  +  + ]:         117007 :     else if (len > 0 && pg_strncasecmp(value, "false", len) == 0)
                                123                 :            139 :         *result = false;
                                124   [ +  -  +  + ]:         116868 :     else if (len > 0 && pg_strncasecmp(value, "yes", len) == 0)
                                125                 :              3 :         *result = true;
                                126   [ +  -  +  + ]:         116865 :     else if (len > 0 && pg_strncasecmp(value, "no", len) == 0)
                                127                 :              3 :         *result = false;
                                128                 :                :     /* 'o' is not unique enough */
 6331 bruce@momjian.us          129         [ +  + ]:         116862 :     else if (pg_strncasecmp(value, "on", (len > 2 ? len : 2)) == 0)
 3141 tgl@sss.pgh.pa.us         130                 :          26375 :         *result = true;
 6331 bruce@momjian.us          131         [ +  + ]:          90487 :     else if (pg_strncasecmp(value, "off", (len > 2 ? len : 2)) == 0)
 3141 tgl@sss.pgh.pa.us         132                 :          84953 :         *result = false;
 6331 bruce@momjian.us          133         [ +  + ]:           5534 :     else if (pg_strcasecmp(value, "1") == 0)
 3141 tgl@sss.pgh.pa.us         134                 :           5521 :         *result = true;
 6331 bruce@momjian.us          135         [ +  + ]:             13 :     else if (pg_strcasecmp(value, "0") == 0)
 3141 tgl@sss.pgh.pa.us         136                 :              4 :         *result = false;
                                137                 :                :     else
                                138                 :                :     {
                                139                 :                :         /* string is not recognized; don't clobber *result */
 3902                           140         [ +  + ]:              9 :         if (name)
 2350 peter@eisentraut.org      141                 :              6 :             pg_log_error("unrecognized value \"%s\" for \"%s\": Boolean expected",
                                142                 :                :                          value, name);
 3141 tgl@sss.pgh.pa.us         143                 :              9 :         valid = false;
                                144                 :                :     }
                                145                 :         117118 :     return valid;
                                146                 :                : }
                                147                 :                : 
                                148                 :                : /*
                                149                 :                :  * Try to interpret "value" as an integer value, and if successful,
                                150                 :                :  * store it in *result.  Otherwise don't clobber *result.
                                151                 :                :  *
                                152                 :                :  * "name" is the name of the variable we're assigning to, to use in error
                                153                 :                :  * report if any.  Pass name == NULL to suppress the error report.
                                154                 :                :  *
                                155                 :                :  * Return true when "value" is syntactically valid, false otherwise.
                                156                 :                :  */
                                157                 :                : bool
                                158                 :          25495 : ParseVariableNum(const char *value, const char *name, int *result)
                                159                 :                : {
                                160                 :                :     char       *end;
                                161                 :                :     long        numval;
                                162                 :                : 
                                163                 :                :     /* Treat "unset" as an empty string, which will lead to error below */
                                164         [ -  + ]:          25495 :     if (value == NULL)
 3139 tgl@sss.pgh.pa.us         165                 :UBC           0 :         value = "";
                                166                 :                : 
 3141 tgl@sss.pgh.pa.us         167                 :CBC       25495 :     errno = 0;
                                168                 :          25495 :     numval = strtol(value, &end, 0);
                                169   [ +  -  +  +  :          25495 :     if (errno == 0 && *end == '\0' && end != value && numval == (int) numval)
                                        +  -  +  - ]
                                170                 :                :     {
                                171                 :          25492 :         *result = (int) numval;
                                172                 :          25492 :         return true;
                                173                 :                :     }
                                174                 :                :     else
                                175                 :                :     {
                                176                 :                :         /* string is not recognized; don't clobber *result */
                                177         [ +  - ]:              3 :         if (name)
 2350 peter@eisentraut.org      178                 :              3 :             pg_log_error("invalid value \"%s\" for \"%s\": integer expected",
                                179                 :                :                          value, name);
 3141 tgl@sss.pgh.pa.us         180                 :              3 :         return false;
                                181                 :                :     }
                                182                 :                : }
                                183                 :                : 
                                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
  165 dgustafsson@postgres      195                 :           8489 : 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   [ +  -  -  + ]:           8489 :     if ((value == NULL) || (*value == '\0'))
                                205                 :                :     {
  165 dgustafsson@postgres      206         [ #  # ]:UBC           0 :         if (name)
   82 peter@eisentraut.org      207                 :              0 :             pg_log_error("invalid input syntax for variable \"%s\"", name);
  165 dgustafsson@postgres      208                 :              0 :         return false;
                                209                 :                :     }
                                210                 :                : 
  165 dgustafsson@postgres      211                 :CBC        8489 :     errno = 0;
                                212                 :           8489 :     dblval = strtod(value, &end);
                                213   [ +  +  +  -  :           8489 :     if (errno == 0 && *end == '\0' && end != value)
                                              +  - ]
                                214                 :                :     {
                                215         [ -  + ]:           8488 :         if (dblval < min)
                                216                 :                :         {
  165 dgustafsson@postgres      217         [ #  # ]:UBC           0 :             if (name)
   82 peter@eisentraut.org      218                 :              0 :                 pg_log_error("invalid value \"%s\" for variable \"%s\": must be greater than %.2f",
                                219                 :                :                              value, name, min);
  165 dgustafsson@postgres      220                 :              0 :             return false;
                                221                 :                :         }
  165 dgustafsson@postgres      222         [ -  + ]:CBC        8488 :         else if (dblval > max)
                                223                 :                :         {
  165 dgustafsson@postgres      224         [ #  # ]:UBC           0 :             if (name)
   82 peter@eisentraut.org      225                 :              0 :                 pg_log_error("invalid value \"%s\" for variable \"%s\": must be less than %.2f",
                                226                 :                :                              value, name, max);
                                227                 :                :         }
  165 dgustafsson@postgres      228                 :CBC        8488 :         *result = dblval;
                                229                 :           8488 :         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                 :                :      */
  163                           237   [ +  -  +  - ]:              1 :     else if ((errno == ERANGE) &&
  165                           238   [ -  +  -  - ]:              1 :              (dblval == 0.0 || dblval >= HUGE_VAL || dblval <= -HUGE_VAL))
                                239                 :                :     {
                                240         [ +  - ]:              1 :         if (name)
   82 peter@eisentraut.org      241                 :              1 :             pg_log_error("value \"%s\" is out of range for variable \"%s\"", value, name);
  165 dgustafsson@postgres      242                 :              1 :         return false;
                                243                 :                :     }
                                244                 :                :     else
                                245                 :                :     {
  165 dgustafsson@postgres      246         [ #  # ]:UBC           0 :         if (name)
   82 peter@eisentraut.org      247                 :              0 :             pg_log_error("invalid value \"%s\" for variable \"%s\"", value, name);
  165 dgustafsson@postgres      248                 :              0 :         return false;
                                249                 :                :     }
                                250                 :                : }
                                251                 :                : 
                                252                 :                : /*
                                253                 :                :  * Print values of all variables.
                                254                 :                :  */
                                255                 :                : void
 8206 bruce@momjian.us          256                 :              0 : PrintVariables(VariableSpace space)
                                257                 :                : {
                                258                 :                :     struct _variable *ptr;
                                259                 :                : 
 7017 tgl@sss.pgh.pa.us         260         [ #  # ]:              0 :     if (!space)
                                261                 :              0 :         return;
                                262                 :                : 
 8069 bruce@momjian.us          263         [ #  # ]:              0 :     for (ptr = space->next; ptr; ptr = ptr->next)
                                264                 :                :     {
 6948 tgl@sss.pgh.pa.us         265         [ #  # ]:              0 :         if (ptr->value)
                                266                 :              0 :             printf("%s = '%s'\n", ptr->name, ptr->value);
 7024                           267         [ #  # ]:              0 :         if (cancel_pressed)
                                268                 :              0 :             break;
                                269                 :                :     }
                                270                 :                : }
                                271                 :                : 
                                272                 :                : /*
                                273                 :                :  * Set the variable named "name" to value "value",
                                274                 :                :  * or delete it if "value" is NULL.
                                275                 :                :  *
                                276                 :                :  * Returns true if successful, false if not; in the latter case a suitable
                                277                 :                :  * error message has been printed, except for the unexpected case of
                                278                 :                :  * space or name being NULL.
                                279                 :                :  */
                                280                 :                : bool
 9438 bruce@momjian.us          281                 :CBC     1363903 : SetVariable(VariableSpace space, const char *name, const char *value)
                                282                 :                : {
                                283                 :                :     struct _variable *current,
                                284                 :                :                *previous;
                                285                 :                : 
 3141 tgl@sss.pgh.pa.us         286   [ +  -  -  + ]:        1363903 :     if (!space || !name)
 9438 bruce@momjian.us          287                 :UBC           0 :         return false;
                                288                 :                : 
 5125 tgl@sss.pgh.pa.us         289         [ +  + ]:CBC     1363903 :     if (!valid_variable_name(name))
                                290                 :                :     {
                                291                 :                :         /* Deletion of non-existent variable is not an error */
 3139                           292         [ -  + ]:              6 :         if (!value)
 3139 tgl@sss.pgh.pa.us         293                 :UBC           0 :             return true;
 2350 peter@eisentraut.org      294                 :CBC           6 :         pg_log_error("invalid variable name: \"%s\"", name);
 9438 bruce@momjian.us          295                 :              6 :         return false;
                                296                 :                :     }
                                297                 :                : 
 7017 tgl@sss.pgh.pa.us         298                 :        1363897 :     for (previous = space, current = space->next;
                                299         [ +  + ]:       29468987 :          current;
                                300                 :       28105090 :          previous = current, current = current->next)
                                301                 :                :     {
 3139                           302                 :       29468648 :         int         cmp = strcmp(current->name, name);
                                303                 :                : 
                                304         [ +  + ]:       29468648 :         if (cmp == 0)
                                305                 :                :         {
                                306                 :                :             /*
                                307                 :                :              * Found entry, so update, unless assign hook returns false.
                                308                 :                :              *
                                309                 :                :              * We must duplicate the passed value to start with.  This
                                310                 :                :              * simplifies the API for substitute hooks.  Moreover, some assign
                                311                 :                :              * hooks assume that the passed value has the same lifespan as the
                                312                 :                :              * variable.  Having to free the string again on failure is a
                                313                 :                :              * small price to pay for keeping these APIs simple.
                                314                 :                :              */
                                315         [ +  + ]:        1193246 :             char       *new_value = value ? pg_strdup(value) : NULL;
                                316                 :                :             bool        confirmed;
                                317                 :                : 
                                318         [ +  + ]:        1193246 :             if (current->substitute_hook)
 2921 peter_e@gmx.net           319                 :          33063 :                 new_value = current->substitute_hook(new_value);
                                320                 :                : 
 6948 tgl@sss.pgh.pa.us         321         [ +  + ]:        1193246 :             if (current->assign_hook)
 2921 peter_e@gmx.net           322                 :          58518 :                 confirmed = current->assign_hook(new_value);
                                323                 :                :             else
 3141 tgl@sss.pgh.pa.us         324                 :        1134728 :                 confirmed = true;
                                325                 :                : 
                                326         [ +  + ]:        1193246 :             if (confirmed)
                                327                 :                :             {
 1177 peter@eisentraut.org      328                 :        1193236 :                 pg_free(current->value);
 3141 tgl@sss.pgh.pa.us         329                 :        1193236 :                 current->value = new_value;
                                330                 :                : 
                                331                 :                :                 /*
                                332                 :                :                  * If we deleted the value, and there are no hooks to
                                333                 :                :                  * remember, we can discard the variable altogether.
                                334                 :                :                  */
 3139                           335         [ +  + ]:        1193236 :                 if (new_value == NULL &&
                                336         [ +  - ]:              3 :                     current->substitute_hook == NULL &&
                                337         [ +  - ]:              3 :                     current->assign_hook == NULL)
                                338                 :                :                 {
                                339                 :              3 :                     previous->next = current->next;
                                340                 :              3 :                     free(current->name);
                                341                 :              3 :                     free(current);
                                342                 :                :                 }
                                343                 :                :             }
                                344                 :                :             else
 2999                           345                 :             10 :                 pg_free(new_value); /* current->value is left unchanged */
                                346                 :                : 
 3141                           347                 :        1193246 :             return confirmed;
                                348                 :                :         }
 3139                           349         [ +  + ]:       28275402 :         if (cmp > 0)
                                350                 :         170312 :             break;              /* it's not there */
                                351                 :                :     }
                                352                 :                : 
                                353                 :                :     /* not present, make new entry ... unless we were asked to delete */
                                354         [ +  + ]:         170651 :     if (value)
                                355                 :                :     {
                                356                 :         153966 :         current = pg_malloc(sizeof *current);
                                357                 :         153966 :         current->name = pg_strdup(name);
                                358                 :         153966 :         current->value = pg_strdup(value);
                                359                 :         153966 :         current->substitute_hook = NULL;
                                360                 :         153966 :         current->assign_hook = NULL;
                                361                 :         153966 :         current->next = previous->next;
                                362                 :         153966 :         previous->next = current;
                                363                 :                :     }
 6948                           364                 :         170651 :     return true;
                                365                 :                : }
                                366                 :                : 
                                367                 :                : /*
                                368                 :                :  * Attach substitute and/or assign hook functions to the named variable.
                                369                 :                :  * If you need only one hook, pass NULL for the other.
                                370                 :                :  *
                                371                 :                :  * If the variable doesn't already exist, create it with value NULL, just so
                                372                 :                :  * we have a place to store the hook function(s).  (The substitute hook might
                                373                 :                :  * immediately change the NULL to something else; if not, this state is
                                374                 :                :  * externally the same as the variable not being defined.)
                                375                 :                :  *
                                376                 :                :  * The substitute hook, if given, is immediately called on the variable's
                                377                 :                :  * value.  Then the assign hook, if given, is called on the variable's value.
                                378                 :                :  * This is meant to let it update any derived psql state.  If the assign hook
                                379                 :                :  * doesn't like the current value, it will print a message to that effect,
                                380                 :                :  * but we'll ignore it.  Generally we do not expect any such failure here,
                                381                 :                :  * because this should get called before any user-supplied value is assigned.
                                382                 :                :  */
                                383                 :                : void
 3139                           384                 :         195155 : SetVariableHooks(VariableSpace space, const char *name,
                                385                 :                :                  VariableSubstituteHook shook,
                                386                 :                :                  VariableAssignHook ahook)
                                387                 :                : {
                                388                 :                :     struct _variable *current,
                                389                 :                :                *previous;
                                390                 :                : 
 3141                           391   [ +  -  -  + ]:         195155 :     if (!space || !name)
 3141 tgl@sss.pgh.pa.us         392                 :UBC           0 :         return;
                                393                 :                : 
 5125 tgl@sss.pgh.pa.us         394         [ -  + ]:CBC      195155 :     if (!valid_variable_name(name))
 3141 tgl@sss.pgh.pa.us         395                 :UBC           0 :         return;
                                396                 :                : 
 6948 tgl@sss.pgh.pa.us         397                 :CBC      195155 :     for (previous = space, current = space->next;
                                398         [ +  + ]:        1484875 :          current;
                                399                 :        1289720 :          previous = current, current = current->next)
                                400                 :                :     {
 3139                           401                 :        1425480 :         int         cmp = strcmp(current->name, name);
                                402                 :                : 
                                403         [ -  + ]:        1425480 :         if (cmp == 0)
                                404                 :                :         {
                                405                 :                :             /* found entry, so update */
 3139 tgl@sss.pgh.pa.us         406                 :UBC           0 :             current->substitute_hook = shook;
                                407                 :              0 :             current->assign_hook = ahook;
                                408         [ #  # ]:              0 :             if (shook)
                                409                 :              0 :                 current->value = (*shook) (current->value);
                                410         [ #  # ]:              0 :             if (ahook)
                                411                 :              0 :                 (void) (*ahook) (current->value);
 3141                           412                 :              0 :             return;
                                413                 :                :         }
 3139 tgl@sss.pgh.pa.us         414         [ +  + ]:CBC     1425480 :         if (cmp > 0)
                                415                 :         135760 :             break;              /* it's not there */
                                416                 :                :     }
                                417                 :                : 
                                418                 :                :     /* not present, make new entry */
 6948                           419                 :         195155 :     current = pg_malloc(sizeof *current);
                                420                 :         195155 :     current->name = pg_strdup(name);
                                421                 :         195155 :     current->value = NULL;
 3139                           422                 :         195155 :     current->substitute_hook = shook;
                                423                 :         195155 :     current->assign_hook = ahook;
                                424                 :         195155 :     current->next = previous->next;
 6948                           425                 :         195155 :     previous->next = current;
 3139                           426         [ +  + ]:         195155 :     if (shook)
                                427                 :         161215 :         current->value = (*shook) (current->value);
                                428         [ +  - ]:         195155 :     if (ahook)
                                429                 :         195155 :         (void) (*ahook) (current->value);
                                430                 :                : }
                                431                 :                : 
                                432                 :                : /*
                                433                 :                :  * Return true iff the named variable has substitute and/or assign hook
                                434                 :                :  * functions.
                                435                 :                :  */
                                436                 :                : bool
 1762 noah@leadboat.com         437                 :            458 : VariableHasHook(VariableSpace space, const char *name)
                                438                 :                : {
                                439                 :                :     struct _variable *current;
                                440                 :                : 
                                441         [ -  + ]:            458 :     Assert(space);
                                442         [ -  + ]:            458 :     Assert(name);
                                443                 :                : 
                                444         [ +  + ]:          22778 :     for (current = space->next; current; current = current->next)
                                445                 :                :     {
                                446                 :          22613 :         int         cmp = strcmp(current->name, name);
                                447                 :                : 
                                448         [ +  + ]:          22613 :         if (cmp == 0)
                                449         [ +  + ]:            129 :             return (current->substitute_hook != NULL ||
                                450         [ -  + ]:             63 :                     current->assign_hook != NULL);
                                451         [ +  + ]:          22547 :         if (cmp > 0)
                                452                 :            227 :             break;              /* it's not there */
                                453                 :                :     }
                                454                 :                : 
                                455                 :            392 :     return false;
                                456                 :                : }
                                457                 :                : 
                                458                 :                : /*
                                459                 :                :  * Convenience function to set a variable's value to "on".
                                460                 :                :  */
                                461                 :                : bool
 9337 peter_e@gmx.net           462                 :          24274 : SetVariableBool(VariableSpace space, const char *name)
                                463                 :                : {
 8106 tgl@sss.pgh.pa.us         464                 :          24274 :     return SetVariable(space, name, "on");
                                465                 :                : }
                                466                 :                : 
                                467                 :                : /*
                                468                 :                :  * Attempt to delete variable.
                                469                 :                :  *
                                470                 :                :  * If unsuccessful, print a message and return "false".
                                471                 :                :  * Deleting a nonexistent variable is not an error.
                                472                 :                :  */
                                473                 :                : bool
 9438 bruce@momjian.us          474                 :UBC           0 : DeleteVariable(VariableSpace space, const char *name)
                                475                 :                : {
 3139 tgl@sss.pgh.pa.us         476                 :              0 :     return SetVariable(space, name, NULL);
                                477                 :                : }
                                478                 :                : 
                                479                 :                : /*
                                480                 :                :  * Emit error with suggestions for variables or commands
                                481                 :                :  * accepting enum-style arguments.
                                482                 :                :  * This function just exists to standardize the wording.
                                483                 :                :  * suggestions should follow the format "fee, fi, fo, fum".
                                484                 :                :  */
                                485                 :                : void
 3141 tgl@sss.pgh.pa.us         486                 :CBC           3 : PsqlVarEnumError(const char *name, const char *value, const char *suggestions)
                                487                 :                : {
 2350 peter@eisentraut.org      488                 :              3 :     pg_log_error("unrecognized value \"%s\" for \"%s\"\n"
                                489                 :                :                  "Available values are: %s.",
                                490                 :                :                  value, name, suggestions);
 3141 tgl@sss.pgh.pa.us         491                 :              3 : }
        

Generated by: LCOV version 2.4-beta