LCOV - code coverage report
Current view: top level - src/backend/utils/misc - guc.c (source / functions) Coverage Total Hit
Test: Code coverage Lines: 68.0 % 2733 1859
Test Date: 2026-01-26 10:56:24 Functions: 85.0 % 100 85
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 43.0 % 2281 981

             Branch data     Line data    Source code
       1                 :             : /*--------------------------------------------------------------------
       2                 :             :  * guc.c
       3                 :             :  *
       4                 :             :  * Support for grand unified configuration scheme, including SET
       5                 :             :  * command, configuration file, and command line options.
       6                 :             :  *
       7                 :             :  * This file contains the generic option processing infrastructure.
       8                 :             :  * guc_funcs.c contains SQL-level functionality, including SET/SHOW
       9                 :             :  * commands and various system-administration SQL functions.
      10                 :             :  * guc_tables.c contains the arrays that define all the built-in
      11                 :             :  * GUC variables.  Code that implements variable-specific behavior
      12                 :             :  * is scattered around the system in check, assign, and show hooks.
      13                 :             :  *
      14                 :             :  * See src/backend/utils/misc/README for more information.
      15                 :             :  *
      16                 :             :  *
      17                 :             :  * Copyright (c) 2000-2026, PostgreSQL Global Development Group
      18                 :             :  * Written by Peter Eisentraut <peter_e@gmx.net>.
      19                 :             :  *
      20                 :             :  * IDENTIFICATION
      21                 :             :  *        src/backend/utils/misc/guc.c
      22                 :             :  *
      23                 :             :  *--------------------------------------------------------------------
      24                 :             :  */
      25                 :             : #include "postgres.h"
      26                 :             : 
      27                 :             : #include <limits.h>
      28                 :             : #include <math.h>
      29                 :             : #include <sys/stat.h>
      30                 :             : #include <unistd.h>
      31                 :             : 
      32                 :             : #include "access/xact.h"
      33                 :             : #include "access/xlog.h"
      34                 :             : #include "catalog/objectaccess.h"
      35                 :             : #include "catalog/pg_authid.h"
      36                 :             : #include "catalog/pg_parameter_acl.h"
      37                 :             : #include "catalog/pg_type.h"
      38                 :             : #include "guc_internal.h"
      39                 :             : #include "libpq/pqformat.h"
      40                 :             : #include "libpq/protocol.h"
      41                 :             : #include "miscadmin.h"
      42                 :             : #include "parser/scansup.h"
      43                 :             : #include "port/pg_bitutils.h"
      44                 :             : #include "storage/fd.h"
      45                 :             : #include "storage/lwlock.h"
      46                 :             : #include "storage/shmem.h"
      47                 :             : #include "tcop/tcopprot.h"
      48                 :             : #include "utils/acl.h"
      49                 :             : #include "utils/builtins.h"
      50                 :             : #include "utils/conffiles.h"
      51                 :             : #include "utils/guc_tables.h"
      52                 :             : #include "utils/memutils.h"
      53                 :             : #include "utils/timestamp.h"
      54                 :             : 
      55                 :             : 
      56                 :             : #define CONFIG_FILENAME "postgresql.conf"
      57                 :             : #define HBA_FILENAME    "pg_hba.conf"
      58                 :             : #define IDENT_FILENAME  "pg_ident.conf"
      59                 :             : 
      60                 :             : #ifdef EXEC_BACKEND
      61                 :             : #define CONFIG_EXEC_PARAMS "global/config_exec_params"
      62                 :             : #define CONFIG_EXEC_PARAMS_NEW "global/config_exec_params.new"
      63                 :             : #endif
      64                 :             : 
      65                 :             : /*
      66                 :             :  * Precision with which REAL type guc values are to be printed for GUC
      67                 :             :  * serialization.
      68                 :             :  */
      69                 :             : #define REALTYPE_PRECISION 17
      70                 :             : 
      71                 :             : /*
      72                 :             :  * Safe search path when executing code as the table owner, such as during
      73                 :             :  * maintenance operations.
      74                 :             :  */
      75                 :             : #define GUC_SAFE_SEARCH_PATH "pg_catalog, pg_temp"
      76                 :             : 
      77                 :             : static int      GUC_check_errcode_value;
      78                 :             : 
      79                 :             : static List *reserved_class_prefix = NIL;
      80                 :             : 
      81                 :             : /* global variables for check hook support */
      82                 :             : char       *GUC_check_errmsg_string;
      83                 :             : char       *GUC_check_errdetail_string;
      84                 :             : char       *GUC_check_errhint_string;
      85                 :             : 
      86                 :             : 
      87                 :             : /*
      88                 :             :  * Unit conversion tables.
      89                 :             :  *
      90                 :             :  * There are two tables, one for memory units, and another for time units.
      91                 :             :  * For each supported conversion from one unit to another, we have an entry
      92                 :             :  * in the table.
      93                 :             :  *
      94                 :             :  * To keep things simple, and to avoid possible roundoff error,
      95                 :             :  * conversions are never chained.  There needs to be a direct conversion
      96                 :             :  * between all units (of the same type).
      97                 :             :  *
      98                 :             :  * The conversions for each base unit must be kept in order from greatest to
      99                 :             :  * smallest human-friendly unit; convert_xxx_from_base_unit() rely on that.
     100                 :             :  * (The order of the base-unit groups does not matter.)
     101                 :             :  */
     102                 :             : #define MAX_UNIT_LEN            3       /* length of longest recognized unit string */
     103                 :             : 
     104                 :             : typedef struct
     105                 :             : {
     106                 :             :         char            unit[MAX_UNIT_LEN + 1]; /* unit, as a string, like "kB" or
     107                 :             :                                                                                  * "min" */
     108                 :             :         int                     base_unit;              /* GUC_UNIT_XXX */
     109                 :             :         double          multiplier;             /* Factor for converting unit -> base_unit */
     110                 :             : } unit_conversion;
     111                 :             : 
     112                 :             : /* Ensure that the constants in the tables don't overflow or underflow */
     113                 :             : #if BLCKSZ < 1024 || BLCKSZ > (1024*1024)
     114                 :             : #error BLCKSZ must be between 1KB and 1MB
     115                 :             : #endif
     116                 :             : #if XLOG_BLCKSZ < 1024 || XLOG_BLCKSZ > (1024*1024)
     117                 :             : #error XLOG_BLCKSZ must be between 1KB and 1MB
     118                 :             : #endif
     119                 :             : 
     120                 :             : static const char *const memory_units_hint = gettext_noop("Valid units for this parameter are \"B\", \"kB\", \"MB\", \"GB\", and \"TB\".");
     121                 :             : 
     122                 :             : static const unit_conversion memory_unit_conversion_table[] =
     123                 :             : {
     124                 :             :         {"TB", GUC_UNIT_BYTE, 1024.0 * 1024.0 * 1024.0 * 1024.0},
     125                 :             :         {"GB", GUC_UNIT_BYTE, 1024.0 * 1024.0 * 1024.0},
     126                 :             :         {"MB", GUC_UNIT_BYTE, 1024.0 * 1024.0},
     127                 :             :         {"kB", GUC_UNIT_BYTE, 1024.0},
     128                 :             :         {"B", GUC_UNIT_BYTE, 1.0},
     129                 :             : 
     130                 :             :         {"TB", GUC_UNIT_KB, 1024.0 * 1024.0 * 1024.0},
     131                 :             :         {"GB", GUC_UNIT_KB, 1024.0 * 1024.0},
     132                 :             :         {"MB", GUC_UNIT_KB, 1024.0},
     133                 :             :         {"kB", GUC_UNIT_KB, 1.0},
     134                 :             :         {"B", GUC_UNIT_KB, 1.0 / 1024.0},
     135                 :             : 
     136                 :             :         {"TB", GUC_UNIT_MB, 1024.0 * 1024.0},
     137                 :             :         {"GB", GUC_UNIT_MB, 1024.0},
     138                 :             :         {"MB", GUC_UNIT_MB, 1.0},
     139                 :             :         {"kB", GUC_UNIT_MB, 1.0 / 1024.0},
     140                 :             :         {"B", GUC_UNIT_MB, 1.0 / (1024.0 * 1024.0)},
     141                 :             : 
     142                 :             :         {"TB", GUC_UNIT_BLOCKS, (1024.0 * 1024.0 * 1024.0) / (BLCKSZ / 1024)},
     143                 :             :         {"GB", GUC_UNIT_BLOCKS, (1024.0 * 1024.0) / (BLCKSZ / 1024)},
     144                 :             :         {"MB", GUC_UNIT_BLOCKS, 1024.0 / (BLCKSZ / 1024)},
     145                 :             :         {"kB", GUC_UNIT_BLOCKS, 1.0 / (BLCKSZ / 1024)},
     146                 :             :         {"B", GUC_UNIT_BLOCKS, 1.0 / BLCKSZ},
     147                 :             : 
     148                 :             :         {"TB", GUC_UNIT_XBLOCKS, (1024.0 * 1024.0 * 1024.0) / (XLOG_BLCKSZ / 1024)},
     149                 :             :         {"GB", GUC_UNIT_XBLOCKS, (1024.0 * 1024.0) / (XLOG_BLCKSZ / 1024)},
     150                 :             :         {"MB", GUC_UNIT_XBLOCKS, 1024.0 / (XLOG_BLCKSZ / 1024)},
     151                 :             :         {"kB", GUC_UNIT_XBLOCKS, 1.0 / (XLOG_BLCKSZ / 1024)},
     152                 :             :         {"B", GUC_UNIT_XBLOCKS, 1.0 / XLOG_BLCKSZ},
     153                 :             : 
     154                 :             :         {""}                                          /* end of table marker */
     155                 :             : };
     156                 :             : 
     157                 :             : static const char *const time_units_hint = gettext_noop("Valid units for this parameter are \"us\", \"ms\", \"s\", \"min\", \"h\", and \"d\".");
     158                 :             : 
     159                 :             : static const unit_conversion time_unit_conversion_table[] =
     160                 :             : {
     161                 :             :         {"d", GUC_UNIT_MS, 1000 * 60 * 60 * 24},
     162                 :             :         {"h", GUC_UNIT_MS, 1000 * 60 * 60},
     163                 :             :         {"min", GUC_UNIT_MS, 1000 * 60},
     164                 :             :         {"s", GUC_UNIT_MS, 1000},
     165                 :             :         {"ms", GUC_UNIT_MS, 1},
     166                 :             :         {"us", GUC_UNIT_MS, 1.0 / 1000},
     167                 :             : 
     168                 :             :         {"d", GUC_UNIT_S, 60 * 60 * 24},
     169                 :             :         {"h", GUC_UNIT_S, 60 * 60},
     170                 :             :         {"min", GUC_UNIT_S, 60},
     171                 :             :         {"s", GUC_UNIT_S, 1},
     172                 :             :         {"ms", GUC_UNIT_S, 1.0 / 1000},
     173                 :             :         {"us", GUC_UNIT_S, 1.0 / (1000 * 1000)},
     174                 :             : 
     175                 :             :         {"d", GUC_UNIT_MIN, 60 * 24},
     176                 :             :         {"h", GUC_UNIT_MIN, 60},
     177                 :             :         {"min", GUC_UNIT_MIN, 1},
     178                 :             :         {"s", GUC_UNIT_MIN, 1.0 / 60},
     179                 :             :         {"ms", GUC_UNIT_MIN, 1.0 / (1000 * 60)},
     180                 :             :         {"us", GUC_UNIT_MIN, 1.0 / (1000 * 1000 * 60)},
     181                 :             : 
     182                 :             :         {""}                                          /* end of table marker */
     183                 :             : };
     184                 :             : 
     185                 :             : /*
     186                 :             :  * To allow continued support of obsolete names for GUC variables, we apply
     187                 :             :  * the following mappings to any unrecognized name.  Note that an old name
     188                 :             :  * should be mapped to a new one only if the new variable has very similar
     189                 :             :  * semantics to the old.
     190                 :             :  */
     191                 :             : static const char *const map_old_guc_names[] = {
     192                 :             :         "sort_mem", "work_mem",
     193                 :             :         "vacuum_mem", "maintenance_work_mem",
     194                 :             :         "ssl_ecdh_curve", "ssl_groups",
     195                 :             :         NULL
     196                 :             : };
     197                 :             : 
     198                 :             : 
     199                 :             : /* Memory context holding all GUC-related data */
     200                 :             : static MemoryContext GUCMemoryContext;
     201                 :             : 
     202                 :             : /*
     203                 :             :  * We use a dynahash table to look up GUCs by name, or to iterate through
     204                 :             :  * all the GUCs.  The gucname field is redundant with gucvar->name, but
     205                 :             :  * dynahash makes it too painful to not store the hash key separately.
     206                 :             :  */
     207                 :             : typedef struct
     208                 :             : {
     209                 :             :         const char *gucname;            /* hash key */
     210                 :             :         struct config_generic *gucvar;  /* -> GUC's defining structure */
     211                 :             : } GUCHashEntry;
     212                 :             : 
     213                 :             : static HTAB *guc_hashtab;               /* entries are GUCHashEntrys */
     214                 :             : 
     215                 :             : /*
     216                 :             :  * In addition to the hash table, variables having certain properties are
     217                 :             :  * linked into these lists, so that we can find them without scanning the
     218                 :             :  * whole hash table.  In most applications, only a small fraction of the
     219                 :             :  * GUCs appear in these lists at any given time.  The usage of the stack
     220                 :             :  * and report lists is stylized enough that they can be slists, but the
     221                 :             :  * nondef list has to be a dlist to avoid O(N) deletes in common cases.
     222                 :             :  */
     223                 :             : static dlist_head guc_nondef_list;      /* list of variables that have source
     224                 :             :                                                                          * different from PGC_S_DEFAULT */
     225                 :             : static slist_head guc_stack_list;       /* list of variables that have non-NULL
     226                 :             :                                                                          * stack */
     227                 :             : static slist_head guc_report_list;      /* list of variables that have the
     228                 :             :                                                                          * GUC_NEEDS_REPORT bit set in status */
     229                 :             : 
     230                 :             : static bool reporting_enabled;  /* true to enable GUC_REPORT */
     231                 :             : 
     232                 :             : static int      GUCNestLevel = 0;       /* 1 when in main transaction */
     233                 :             : 
     234                 :             : 
     235                 :             : static int      guc_var_compare(const void *a, const void *b);
     236                 :             : static uint32 guc_name_hash(const void *key, Size keysize);
     237                 :             : static int      guc_name_match(const void *key1, const void *key2, Size keysize);
     238                 :             : static void InitializeGUCOptionsFromEnvironment(void);
     239                 :             : static void InitializeOneGUCOption(struct config_generic *gconf);
     240                 :             : static void RemoveGUCFromLists(struct config_generic *gconf);
     241                 :             : static void set_guc_source(struct config_generic *gconf, GucSource newsource);
     242                 :             : static void pg_timezone_abbrev_initialize(void);
     243                 :             : static void push_old_value(struct config_generic *gconf, GucAction action);
     244                 :             : static void ReportGUCOption(struct config_generic *record);
     245                 :             : static void set_config_sourcefile(const char *name, char *sourcefile,
     246                 :             :                                                                   int sourceline);
     247                 :             : static void reapply_stacked_values(struct config_generic *variable,
     248                 :             :                                                                    struct config_generic *pHolder,
     249                 :             :                                                                    GucStack *stack,
     250                 :             :                                                                    const char *curvalue,
     251                 :             :                                                                    GucContext curscontext, GucSource cursource,
     252                 :             :                                                                    Oid cursrole);
     253                 :             : static void free_placeholder(struct config_generic *pHolder);
     254                 :             : static bool validate_option_array_item(const char *name, const char *value,
     255                 :             :                                                                            bool skipIfNoPermissions);
     256                 :             : static void write_auto_conf_file(int fd, const char *filename, ConfigVariable *head);
     257                 :             : static void replace_auto_config_value(ConfigVariable **head_p, ConfigVariable **tail_p,
     258                 :             :                                                                           const char *name, const char *value);
     259                 :             : static bool valid_custom_variable_name(const char *name);
     260                 :             : static bool assignable_custom_variable_name(const char *name, bool skip_errors,
     261                 :             :                                                                                         int elevel);
     262                 :             : static void do_serialize(char **destptr, Size *maxbytes,
     263                 :             :                                                  const char *fmt,...) pg_attribute_printf(3, 4);
     264                 :             : static bool call_bool_check_hook(const struct config_generic *conf, bool *newval,
     265                 :             :                                                                  void **extra, GucSource source, int elevel);
     266                 :             : static bool call_int_check_hook(const struct config_generic *conf, int *newval,
     267                 :             :                                                                 void **extra, GucSource source, int elevel);
     268                 :             : static bool call_real_check_hook(const struct config_generic *conf, double *newval,
     269                 :             :                                                                  void **extra, GucSource source, int elevel);
     270                 :             : static bool call_string_check_hook(const struct config_generic *conf, char **newval,
     271                 :             :                                                                    void **extra, GucSource source, int elevel);
     272                 :             : static bool call_enum_check_hook(const struct config_generic *conf, int *newval,
     273                 :             :                                                                  void **extra, GucSource source, int elevel);
     274                 :             : 
     275                 :             : 
     276                 :             : /*
     277                 :             :  * This function handles both actual config file (re)loads and execution of
     278                 :             :  * show_all_file_settings() (i.e., the pg_file_settings view).  In the latter
     279                 :             :  * case we don't apply any of the settings, but we make all the usual validity
     280                 :             :  * checks, and we return the ConfigVariable list so that it can be printed out
     281                 :             :  * by show_all_file_settings().
     282                 :             :  */
     283                 :             : ConfigVariable *
     284                 :          13 : ProcessConfigFileInternal(GucContext context, bool applySettings, int elevel)
     285                 :             : {
     286                 :          13 :         bool            error = false;
     287                 :          13 :         bool            applying = false;
     288                 :          13 :         const char *ConfFileWithError;
     289                 :          13 :         ConfigVariable *head,
     290                 :             :                            *tail;
     291                 :          13 :         HASH_SEQ_STATUS status;
     292                 :          13 :         GUCHashEntry *hentry;
     293                 :             : 
     294                 :             :         /* Parse the main config file into a list of option names and values */
     295                 :          13 :         ConfFileWithError = ConfigFileName;
     296                 :          13 :         head = tail = NULL;
     297                 :             : 
     298   [ +  -  +  - ]:          26 :         if (!ParseConfigFile(ConfigFileName, true,
     299                 :          13 :                                                  NULL, 0, CONF_FILE_START_DEPTH, elevel,
     300                 :             :                                                  &head, &tail))
     301                 :             :         {
     302                 :             :                 /* Syntax error(s) detected in the file, so bail out */
     303                 :           0 :                 error = true;
     304                 :           0 :                 goto bail_out;
     305                 :             :         }
     306                 :             : 
     307                 :             :         /*
     308                 :             :          * Parse the PG_AUTOCONF_FILENAME file, if present, after the main file to
     309                 :             :          * replace any parameters set by ALTER SYSTEM command.  Because this file
     310                 :             :          * is in the data directory, we can't read it until the DataDir has been
     311                 :             :          * set.
     312                 :             :          */
     313         [ +  + ]:          13 :         if (DataDir)
     314                 :             :         {
     315         [ +  - ]:           7 :                 if (!ParseConfigFile(PG_AUTOCONF_FILENAME, false,
     316                 :           7 :                                                          NULL, 0, CONF_FILE_START_DEPTH, elevel,
     317                 :             :                                                          &head, &tail))
     318                 :             :                 {
     319                 :             :                         /* Syntax error(s) detected in the file, so bail out */
     320                 :           0 :                         error = true;
     321                 :           0 :                         ConfFileWithError = PG_AUTOCONF_FILENAME;
     322                 :           0 :                         goto bail_out;
     323                 :             :                 }
     324                 :           7 :         }
     325                 :             :         else
     326                 :             :         {
     327                 :             :                 /*
     328                 :             :                  * If DataDir is not set, the PG_AUTOCONF_FILENAME file cannot be
     329                 :             :                  * read.  In this case, we don't want to accept any settings but
     330                 :             :                  * data_directory from postgresql.conf, because they might be
     331                 :             :                  * overwritten with settings in the PG_AUTOCONF_FILENAME file which
     332                 :             :                  * will be read later. OTOH, since data_directory isn't allowed in the
     333                 :             :                  * PG_AUTOCONF_FILENAME file, it will never be overwritten later.
     334                 :             :                  */
     335                 :           6 :                 ConfigVariable *newlist = NULL;
     336                 :             : 
     337                 :             :                 /*
     338                 :             :                  * Prune all items except the last "data_directory" from the list.
     339                 :             :                  */
     340         [ +  + ]:          85 :                 for (ConfigVariable *item = head; item; item = item->next)
     341                 :             :                 {
     342   [ +  -  +  - ]:          79 :                         if (!item->ignore &&
     343                 :          79 :                                 strcmp(item->name, "data_directory") == 0)
     344                 :           0 :                                 newlist = item;
     345                 :          79 :                 }
     346                 :             : 
     347         [ +  - ]:           6 :                 if (newlist)
     348                 :           0 :                         newlist->next = NULL;
     349                 :           6 :                 head = tail = newlist;
     350                 :             : 
     351                 :             :                 /*
     352                 :             :                  * Quick exit if data_directory is not present in file.
     353                 :             :                  *
     354                 :             :                  * We need not do any further processing, in particular we don't set
     355                 :             :                  * PgReloadTime; that will be set soon by subsequent full loading of
     356                 :             :                  * the config file.
     357                 :             :                  */
     358         [ -  + ]:           6 :                 if (head == NULL)
     359                 :           6 :                         goto bail_out;
     360      [ -  -  + ]:           6 :         }
     361                 :             : 
     362                 :             :         /*
     363                 :             :          * Mark all extant GUC variables as not present in the config file. We
     364                 :             :          * need this so that we can tell below which ones have been removed from
     365                 :             :          * the file since we last processed it.
     366                 :             :          */
     367                 :           7 :         hash_seq_init(&status, guc_hashtab);
     368         [ +  + ]:        2892 :         while ((hentry = (GUCHashEntry *) hash_seq_search(&status)) != NULL)
     369                 :             :         {
     370                 :        2885 :                 struct config_generic *gconf = hentry->gucvar;
     371                 :             : 
     372                 :        2885 :                 gconf->status &= ~GUC_IS_IN_FILE;
     373                 :        2885 :         }
     374                 :             : 
     375                 :             :         /*
     376                 :             :          * Check if all the supplied option names are valid, as an additional
     377                 :             :          * quasi-syntactic check on the validity of the config file.  It is
     378                 :             :          * important that the postmaster and all backends agree on the results of
     379                 :             :          * this phase, else we will have strange inconsistencies about which
     380                 :             :          * processes accept a config file update and which don't.  Hence, unknown
     381                 :             :          * custom variable names have to be accepted without complaint.  For the
     382                 :             :          * same reason, we don't attempt to validate the options' values here.
     383                 :             :          *
     384                 :             :          * In addition, the GUC_IS_IN_FILE flag is set on each existing GUC
     385                 :             :          * variable mentioned in the file; and we detect duplicate entries in the
     386                 :             :          * file and mark the earlier occurrences as ignorable.
     387                 :             :          */
     388         [ +  + ]:         116 :         for (ConfigVariable *item = head; item; item = item->next)
     389                 :             :         {
     390                 :         109 :                 struct config_generic *record;
     391                 :             : 
     392                 :             :                 /* Ignore anything already marked as ignorable */
     393         [ -  + ]:         109 :                 if (item->ignore)
     394                 :           0 :                         continue;
     395                 :             : 
     396                 :             :                 /*
     397                 :             :                  * Try to find the variable; but do not create a custom placeholder if
     398                 :             :                  * it's not there already.
     399                 :             :                  */
     400                 :         109 :                 record = find_option(item->name, false, true, elevel);
     401                 :             : 
     402         [ +  + ]:         109 :                 if (record)
     403                 :             :                 {
     404                 :             :                         /* If it's already marked, then this is a duplicate entry */
     405         [ -  + ]:         105 :                         if (record->status & GUC_IS_IN_FILE)
     406                 :             :                         {
     407                 :             :                                 /*
     408                 :             :                                  * Mark the earlier occurrence(s) as dead/ignorable.  We could
     409                 :             :                                  * avoid the O(N^2) behavior here with some additional state,
     410                 :             :                                  * but it seems unlikely to be worth the trouble.
     411                 :             :                                  */
     412         [ #  # ]:           0 :                                 for (ConfigVariable *pitem = head; pitem != item; pitem = pitem->next)
     413                 :             :                                 {
     414   [ #  #  #  # ]:           0 :                                         if (!pitem->ignore &&
     415                 :           0 :                                                 strcmp(pitem->name, item->name) == 0)
     416                 :           0 :                                                 pitem->ignore = true;
     417                 :           0 :                                 }
     418                 :           0 :                         }
     419                 :             :                         /* Now mark it as present in file */
     420                 :         105 :                         record->status |= GUC_IS_IN_FILE;
     421                 :         105 :                 }
     422         [ +  - ]:           4 :                 else if (!valid_custom_variable_name(item->name))
     423                 :             :                 {
     424                 :             :                         /* Invalid non-custom variable, so complain */
     425   [ #  #  #  #  :           0 :                         ereport(elevel,
          #  #  #  #  #  
                      # ]
     426                 :             :                                         (errcode(ERRCODE_UNDEFINED_OBJECT),
     427                 :             :                                          errmsg("unrecognized configuration parameter \"%s\" in file \"%s\" line %d",
     428                 :             :                                                         item->name,
     429                 :             :                                                         item->filename, item->sourceline)));
     430                 :           0 :                         item->errmsg = pstrdup("unrecognized configuration parameter");
     431                 :           0 :                         error = true;
     432                 :           0 :                         ConfFileWithError = item->filename;
     433                 :           0 :                 }
     434         [ -  + ]:         109 :         }
     435                 :             : 
     436                 :             :         /*
     437                 :             :          * If we've detected any errors so far, we don't want to risk applying any
     438                 :             :          * changes.
     439                 :             :          */
     440         [ -  + ]:           7 :         if (error)
     441                 :           0 :                 goto bail_out;
     442                 :             : 
     443                 :             :         /* Otherwise, set flag that we're beginning to apply changes */
     444                 :           7 :         applying = true;
     445                 :             : 
     446                 :             :         /*
     447                 :             :          * Check for variables having been removed from the config file, and
     448                 :             :          * revert their reset values (and perhaps also effective values) to the
     449                 :             :          * boot-time defaults.  If such a variable can't be changed after startup,
     450                 :             :          * report that and continue.
     451                 :             :          */
     452                 :           7 :         hash_seq_init(&status, guc_hashtab);
     453         [ +  + ]:        2892 :         while ((hentry = (GUCHashEntry *) hash_seq_search(&status)) != NULL)
     454                 :             :         {
     455                 :        2885 :                 struct config_generic *gconf = hentry->gucvar;
     456                 :             : 
     457   [ +  +  +  - ]:        2885 :                 if (gconf->reset_source != PGC_S_FILE ||
     458                 :          24 :                         (gconf->status & GUC_IS_IN_FILE))
     459                 :        2885 :                         continue;
     460         [ #  # ]:           0 :                 if (gconf->context < PGC_SIGHUP)
     461                 :             :                 {
     462                 :             :                         /* The removal can't be effective without a restart */
     463                 :           0 :                         gconf->status |= GUC_PENDING_RESTART;
     464   [ #  #  #  #  :           0 :                         ereport(elevel,
          #  #  #  #  #  
                      # ]
     465                 :             :                                         (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
     466                 :             :                                          errmsg("parameter \"%s\" cannot be changed without restarting the server",
     467                 :             :                                                         gconf->name)));
     468                 :           0 :                         record_config_file_error(psprintf("parameter \"%s\" cannot be changed without restarting the server",
     469                 :           0 :                                                                                           gconf->name),
     470                 :             :                                                                          NULL, 0,
     471                 :             :                                                                          &head, &tail);
     472                 :           0 :                         error = true;
     473                 :           0 :                         continue;
     474                 :             :                 }
     475                 :             : 
     476                 :             :                 /* No more to do if we're just doing show_all_file_settings() */
     477         [ #  # ]:           0 :                 if (!applySettings)
     478                 :           0 :                         continue;
     479                 :             : 
     480                 :             :                 /*
     481                 :             :                  * Reset any "file" sources to "default", else set_config_option will
     482                 :             :                  * not override those settings.
     483                 :             :                  */
     484         [ #  # ]:           0 :                 if (gconf->reset_source == PGC_S_FILE)
     485                 :           0 :                         gconf->reset_source = PGC_S_DEFAULT;
     486         [ #  # ]:           0 :                 if (gconf->source == PGC_S_FILE)
     487                 :           0 :                         set_guc_source(gconf, PGC_S_DEFAULT);
     488         [ #  # ]:           0 :                 for (GucStack *stack = gconf->stack; stack; stack = stack->prev)
     489                 :             :                 {
     490         [ #  # ]:           0 :                         if (stack->source == PGC_S_FILE)
     491                 :           0 :                                 stack->source = PGC_S_DEFAULT;
     492                 :           0 :                 }
     493                 :             : 
     494                 :             :                 /* Now we can re-apply the wired-in default (i.e., the boot_val) */
     495                 :           0 :                 if (set_config_option(gconf->name, NULL,
     496                 :           0 :                                                           context, PGC_S_DEFAULT,
     497         [ #  # ]:           0 :                                                           GUC_ACTION_SET, true, 0, false) > 0)
     498                 :             :                 {
     499                 :             :                         /* Log the change if appropriate */
     500         [ #  # ]:           0 :                         if (context == PGC_SIGHUP)
     501   [ #  #  #  #  :           0 :                                 ereport(elevel,
          #  #  #  #  #  
                      # ]
     502                 :             :                                                 (errmsg("parameter \"%s\" removed from configuration file, reset to default",
     503                 :             :                                                                 gconf->name)));
     504                 :           0 :                 }
     505         [ +  - ]:        2885 :         }
     506                 :             : 
     507                 :             :         /*
     508                 :             :          * Restore any variables determined by environment variables or
     509                 :             :          * dynamically-computed defaults.  This is a no-op except in the case
     510                 :             :          * where one of these had been in the config file and is now removed.
     511                 :             :          *
     512                 :             :          * In particular, we *must not* do this during the postmaster's initial
     513                 :             :          * loading of the file, since the timezone functions in particular should
     514                 :             :          * be run only after initialization is complete.
     515                 :             :          *
     516                 :             :          * XXX this is an unmaintainable crock, because we have to know how to set
     517                 :             :          * (or at least what to call to set) every non-PGC_INTERNAL variable that
     518                 :             :          * could potentially have PGC_S_DYNAMIC_DEFAULT or PGC_S_ENV_VAR source.
     519                 :             :          */
     520   [ +  +  +  - ]:           7 :         if (context == PGC_SIGHUP && applySettings)
     521                 :             :         {
     522                 :           0 :                 InitializeGUCOptionsFromEnvironment();
     523                 :           0 :                 pg_timezone_abbrev_initialize();
     524                 :             :                 /* this selects SQL_ASCII in processes not connected to a database */
     525                 :           0 :                 SetConfigOption("client_encoding", GetDatabaseEncodingName(),
     526                 :             :                                                 PGC_BACKEND, PGC_S_DYNAMIC_DEFAULT);
     527                 :           0 :         }
     528                 :             : 
     529                 :             :         /*
     530                 :             :          * Now apply the values from the config file.
     531                 :             :          */
     532         [ +  + ]:         116 :         for (ConfigVariable *item = head; item; item = item->next)
     533                 :             :         {
     534                 :         109 :                 char       *pre_value = NULL;
     535                 :         109 :                 int                     scres;
     536                 :             : 
     537                 :             :                 /* Ignore anything marked as ignorable */
     538         [ -  + ]:         109 :                 if (item->ignore)
     539                 :           0 :                         continue;
     540                 :             : 
     541                 :             :                 /* In SIGHUP cases in the postmaster, we want to report changes */
     542   [ +  +  -  +  :         109 :                 if (context == PGC_SIGHUP && applySettings && !IsUnderPostmaster)
                   #  # ]
     543                 :             :                 {
     544                 :           0 :                         const char *preval = GetConfigOption(item->name, true, false);
     545                 :             : 
     546                 :             :                         /* If option doesn't exist yet or is NULL, treat as empty string */
     547         [ #  # ]:           0 :                         if (!preval)
     548                 :           0 :                                 preval = "";
     549                 :             :                         /* must dup, else might have dangling pointer below */
     550                 :           0 :                         pre_value = pstrdup(preval);
     551                 :           0 :                 }
     552                 :             : 
     553                 :         218 :                 scres = set_config_option(item->name, item->value,
     554                 :         109 :                                                                   context, PGC_S_FILE,
     555                 :         109 :                                                                   GUC_ACTION_SET, applySettings, 0, false);
     556         [ +  + ]:         109 :                 if (scres > 0)
     557                 :             :                 {
     558                 :             :                         /* variable was updated, so log the change if appropriate */
     559         [ +  - ]:          79 :                         if (pre_value)
     560                 :             :                         {
     561                 :           0 :                                 const char *post_value = GetConfigOption(item->name, true, false);
     562                 :             : 
     563         [ #  # ]:           0 :                                 if (!post_value)
     564                 :           0 :                                         post_value = "";
     565         [ #  # ]:           0 :                                 if (strcmp(pre_value, post_value) != 0)
     566   [ #  #  #  #  :           0 :                                         ereport(elevel,
          #  #  #  #  #  
                      # ]
     567                 :             :                                                         (errmsg("parameter \"%s\" changed to \"%s\"",
     568                 :             :                                                                         item->name, item->value)));
     569                 :           0 :                         }
     570                 :          79 :                         item->applied = true;
     571                 :          79 :                 }
     572         [ +  - ]:          30 :                 else if (scres == 0)
     573                 :             :                 {
     574                 :           0 :                         error = true;
     575                 :           0 :                         item->errmsg = pstrdup("setting could not be applied");
     576                 :           0 :                         ConfFileWithError = item->filename;
     577                 :           0 :                 }
     578                 :             :                 else
     579                 :             :                 {
     580                 :             :                         /* no error, but variable's active value was not changed */
     581                 :          30 :                         item->applied = true;
     582                 :             :                 }
     583                 :             : 
     584                 :             :                 /*
     585                 :             :                  * We should update source location unless there was an error, since
     586                 :             :                  * even if the active value didn't change, the reset value might have.
     587                 :             :                  * (In the postmaster, there won't be a difference, but it does matter
     588                 :             :                  * in backends.)
     589                 :             :                  */
     590   [ +  -  +  + ]:         109 :                 if (scres != 0 && applySettings)
     591                 :         158 :                         set_config_sourcefile(item->name, item->filename,
     592                 :          79 :                                                                   item->sourceline);
     593                 :             : 
     594         [ +  - ]:         109 :                 if (pre_value)
     595                 :           0 :                         pfree(pre_value);
     596         [ -  + ]:         109 :         }
     597                 :             : 
     598                 :             :         /* Remember when we last successfully loaded the config file. */
     599         [ +  + ]:          13 :         if (applySettings)
     600                 :           6 :                 PgReloadTime = GetCurrentTimestamp();
     601                 :             : 
     602                 :             : bail_out:
     603   [ -  +  #  # ]:          13 :         if (error && applySettings)
     604                 :             :         {
     605                 :             :                 /* During postmaster startup, any error is fatal */
     606         [ #  # ]:           0 :                 if (context == PGC_POSTMASTER)
     607   [ #  #  #  # ]:           0 :                         ereport(ERROR,
     608                 :             :                                         (errcode(ERRCODE_CONFIG_FILE_ERROR),
     609                 :             :                                          errmsg("configuration file \"%s\" contains errors",
     610                 :             :                                                         ConfFileWithError)));
     611         [ #  # ]:           0 :                 else if (applying)
     612   [ #  #  #  #  :           0 :                         ereport(elevel,
          #  #  #  #  #  
                      # ]
     613                 :             :                                         (errcode(ERRCODE_CONFIG_FILE_ERROR),
     614                 :             :                                          errmsg("configuration file \"%s\" contains errors; unaffected changes were applied",
     615                 :             :                                                         ConfFileWithError)));
     616                 :             :                 else
     617   [ #  #  #  #  :           0 :                         ereport(elevel,
          #  #  #  #  #  
                      # ]
     618                 :             :                                         (errcode(ERRCODE_CONFIG_FILE_ERROR),
     619                 :             :                                          errmsg("configuration file \"%s\" contains errors; no changes were applied",
     620                 :             :                                                         ConfFileWithError)));
     621                 :           0 :         }
     622                 :             : 
     623                 :             :         /* Successful or otherwise, return the collected data list */
     624                 :          13 :         return head;
     625                 :          13 : }
     626                 :             : 
     627                 :             : 
     628                 :             : /*
     629                 :             :  * Some infrastructure for GUC-related memory allocation
     630                 :             :  *
     631                 :             :  * These functions are generally modeled on libc's malloc/realloc/etc,
     632                 :             :  * but any OOM issue is reported at the specified elevel.
     633                 :             :  * (Thus, control returns only if that's less than ERROR.)
     634                 :             :  */
     635                 :             : void *
     636                 :       69023 : guc_malloc(int elevel, size_t size)
     637                 :             : {
     638                 :       69023 :         void       *data;
     639                 :             : 
     640                 :       69023 :         data = MemoryContextAllocExtended(GUCMemoryContext, size,
     641                 :             :                                                                           MCXT_ALLOC_NO_OOM);
     642         [ +  - ]:       69023 :         if (unlikely(data == NULL))
     643   [ #  #  #  #  :           0 :                 ereport(elevel,
          #  #  #  #  #  
                      # ]
     644                 :             :                                 (errcode(ERRCODE_OUT_OF_MEMORY),
     645                 :             :                                  errmsg("out of memory")));
     646                 :      138046 :         return data;
     647                 :       69023 : }
     648                 :             : 
     649                 :             : void *
     650                 :           0 : guc_realloc(int elevel, void *old, size_t size)
     651                 :             : {
     652                 :           0 :         void       *data;
     653                 :             : 
     654         [ #  # ]:           0 :         if (old != NULL)
     655                 :             :         {
     656                 :             :                 /* This is to help catch old code that malloc's GUC data. */
     657         [ #  # ]:           0 :                 Assert(GetMemoryChunkContext(old) == GUCMemoryContext);
     658                 :           0 :                 data = repalloc_extended(old, size,
     659                 :             :                                                                  MCXT_ALLOC_NO_OOM);
     660                 :           0 :         }
     661                 :             :         else
     662                 :             :         {
     663                 :             :                 /* Like realloc(3), but not like repalloc(), we allow old == NULL. */
     664                 :           0 :                 data = MemoryContextAllocExtended(GUCMemoryContext, size,
     665                 :             :                                                                                   MCXT_ALLOC_NO_OOM);
     666                 :             :         }
     667         [ #  # ]:           0 :         if (unlikely(data == NULL))
     668   [ #  #  #  #  :           0 :                 ereport(elevel,
          #  #  #  #  #  
                      # ]
     669                 :             :                                 (errcode(ERRCODE_OUT_OF_MEMORY),
     670                 :             :                                  errmsg("out of memory")));
     671                 :           0 :         return data;
     672                 :           0 : }
     673                 :             : 
     674                 :             : char *
     675                 :       55072 : guc_strdup(int elevel, const char *src)
     676                 :             : {
     677                 :       55072 :         char       *data;
     678                 :       55072 :         size_t          len = strlen(src) + 1;
     679                 :             : 
     680                 :       55072 :         data = guc_malloc(elevel, len);
     681         [ -  + ]:       55072 :         if (likely(data != NULL))
     682                 :       55072 :                 memcpy(data, src, len);
     683                 :      110144 :         return data;
     684                 :       55072 : }
     685                 :             : 
     686                 :             : void
     687                 :       96132 : guc_free(void *ptr)
     688                 :             : {
     689                 :             :         /*
     690                 :             :          * Historically, GUC-related code has relied heavily on the ability to do
     691                 :             :          * free(NULL), so we allow that here even though pfree() doesn't.
     692                 :             :          */
     693         [ +  + ]:       96132 :         if (ptr != NULL)
     694                 :             :         {
     695                 :             :                 /* This is to help catch old code that malloc's GUC data. */
     696         [ +  - ]:       55099 :                 Assert(GetMemoryChunkContext(ptr) == GUCMemoryContext);
     697                 :       55099 :                 pfree(ptr);
     698                 :       55099 :         }
     699                 :       96132 : }
     700                 :             : 
     701                 :             : 
     702                 :             : /*
     703                 :             :  * Detect whether strval is referenced anywhere in a GUC string item
     704                 :             :  */
     705                 :             : static bool
     706                 :       98288 : string_field_used(struct config_generic *conf, char *strval)
     707                 :             : {
     708         [ +  + ]:       98288 :         if (strval == *(conf->_string.variable) ||
     709   [ +  +  -  + ]:       55202 :                 strval == conf->_string.reset_val ||
     710                 :       32972 :                 strval == conf->_string.boot_val)
     711                 :       65316 :                 return true;
     712   [ +  +  -  +  :       57420 :         for (GucStack *stack = conf->stack; stack; stack = stack->prev)
                      + ]
     713                 :             :         {
     714   [ +  +  +  + ]:       24448 :                 if (strval == stack->prior.val.stringval ||
     715                 :       18632 :                         strval == stack->masked.val.stringval)
     716                 :        5817 :                         return true;
     717                 :       18631 :         }
     718                 :       27155 :         return false;
     719                 :       98288 : }
     720                 :             : 
     721                 :             : /*
     722                 :             :  * Support for assigning to a field of a string GUC item.  Free the prior
     723                 :             :  * value if it's not referenced anywhere else in the item (including stacked
     724                 :             :  * states).
     725                 :             :  */
     726                 :             : static void
     727                 :      101244 : set_string_field(struct config_generic *conf, char **field, char *newval)
     728                 :             : {
     729                 :      101244 :         char       *oldval = *field;
     730                 :             : 
     731                 :             :         /* Do the assignment */
     732                 :      101244 :         *field = newval;
     733                 :             : 
     734                 :             :         /* Free old value if it's not NULL and isn't referenced anymore */
     735   [ +  +  +  + ]:      101244 :         if (oldval && !string_field_used(conf, oldval))
     736                 :       27123 :                 guc_free(oldval);
     737                 :      101244 : }
     738                 :             : 
     739                 :             : /*
     740                 :             :  * Detect whether an "extra" struct is referenced anywhere in a GUC item
     741                 :             :  */
     742                 :             : static bool
     743                 :       20402 : extra_field_used(struct config_generic *gconf, void *extra)
     744                 :             : {
     745         [ +  + ]:       20402 :         if (extra == gconf->extra)
     746                 :        7764 :                 return true;
     747         [ +  + ]:       12638 :         if (extra == gconf->reset_extra)
     748                 :        5766 :                 return true;
     749   [ +  +  -  +  :        8887 :         for (GucStack *stack = gconf->stack; stack; stack = stack->prev)
                      + ]
     750                 :             :         {
     751   [ +  +  +  + ]:        2015 :                 if (extra == stack->prior.extra ||
     752                 :        1046 :                         extra == stack->masked.extra)
     753                 :         970 :                         return true;
     754                 :        1045 :         }
     755                 :             : 
     756                 :        5902 :         return false;
     757                 :       20402 : }
     758                 :             : 
     759                 :             : /*
     760                 :             :  * Support for assigning to an "extra" field of a GUC item.  Free the prior
     761                 :             :  * value if it's not referenced anywhere else in the item (including stacked
     762                 :             :  * states).
     763                 :             :  */
     764                 :             : static void
     765                 :      145364 : set_extra_field(struct config_generic *gconf, void **field, void *newval)
     766                 :             : {
     767                 :      145364 :         void       *oldval = *field;
     768                 :             : 
     769                 :             :         /* Do the assignment */
     770                 :      145364 :         *field = newval;
     771                 :             : 
     772                 :             :         /* Free old value if it's not NULL and isn't referenced anymore */
     773   [ +  +  +  + ]:      145364 :         if (oldval && !extra_field_used(gconf, oldval))
     774                 :        5893 :                 guc_free(oldval);
     775                 :      145364 : }
     776                 :             : 
     777                 :             : /*
     778                 :             :  * Support for copying a variable's active value into a stack entry.
     779                 :             :  * The "extra" field associated with the active value is copied, too.
     780                 :             :  *
     781                 :             :  * NB: be sure stringval and extra fields of a new stack entry are
     782                 :             :  * initialized to NULL before this is used, else we'll try to guc_free() them.
     783                 :             :  */
     784                 :             : static void
     785                 :           0 : set_stack_value(struct config_generic *gconf, config_var_value *val)
     786                 :             : {
     787   [ #  #  #  #  :           0 :         switch (gconf->vartype)
                   #  # ]
     788                 :             :         {
     789                 :             :                 case PGC_BOOL:
     790                 :           0 :                         val->val.boolval = *gconf->_bool.variable;
     791                 :           0 :                         break;
     792                 :             :                 case PGC_INT:
     793                 :           0 :                         val->val.intval = *gconf->_int.variable;
     794                 :           0 :                         break;
     795                 :             :                 case PGC_REAL:
     796                 :           0 :                         val->val.realval = *gconf->_real.variable;
     797                 :           0 :                         break;
     798                 :             :                 case PGC_STRING:
     799                 :           0 :                         set_string_field(gconf, &(val->val.stringval), *gconf->_string.variable);
     800                 :           0 :                         break;
     801                 :             :                 case PGC_ENUM:
     802                 :           0 :                         val->val.enumval = *gconf->_enum.variable;
     803                 :           0 :                         break;
     804                 :             :         }
     805                 :           0 :         set_extra_field(gconf, &(val->extra), gconf->extra);
     806                 :           0 : }
     807                 :             : 
     808                 :             : /*
     809                 :             :  * Support for discarding a no-longer-needed value in a stack entry.
     810                 :             :  * The "extra" field associated with the stack entry is cleared, too.
     811                 :             :  */
     812                 :             : static void
     813                 :        6164 : discard_stack_value(struct config_generic *gconf, config_var_value *val)
     814                 :             : {
     815      [ -  +  + ]:        6164 :         switch (gconf->vartype)
     816                 :             :         {
     817                 :             :                 case PGC_BOOL:
     818                 :             :                 case PGC_INT:
     819                 :             :                 case PGC_REAL:
     820                 :             :                 case PGC_ENUM:
     821                 :             :                         /* no need to do anything */
     822                 :        4580 :                         break;
     823                 :             :                 case PGC_STRING:
     824                 :        3168 :                         set_string_field(gconf,
     825                 :        1584 :                                                          &(val->val.stringval),
     826                 :             :                                                          NULL);
     827                 :        1584 :                         break;
     828                 :             :         }
     829                 :        6164 :         set_extra_field(gconf, &(val->extra), NULL);
     830                 :        6164 : }
     831                 :             : 
     832                 :             : 
     833                 :             : /*
     834                 :             :  * Fetch a palloc'd, sorted array of GUC struct pointers
     835                 :             :  *
     836                 :             :  * The array length is returned into *num_vars.
     837                 :             :  */
     838                 :             : struct config_generic **
     839                 :           7 : get_guc_variables(int *num_vars)
     840                 :             : {
     841                 :           7 :         struct config_generic **result;
     842                 :           7 :         HASH_SEQ_STATUS status;
     843                 :           7 :         GUCHashEntry *hentry;
     844                 :           7 :         int                     i;
     845                 :             : 
     846                 :           7 :         *num_vars = hash_get_num_entries(guc_hashtab);
     847                 :           7 :         result = palloc_array(struct config_generic *, *num_vars);
     848                 :             : 
     849                 :             :         /* Extract pointers from the hash table */
     850                 :           7 :         i = 0;
     851                 :           7 :         hash_seq_init(&status, guc_hashtab);
     852         [ +  + ]:        2968 :         while ((hentry = (GUCHashEntry *) hash_seq_search(&status)) != NULL)
     853                 :        2961 :                 result[i++] = hentry->gucvar;
     854         [ +  - ]:           7 :         Assert(i == *num_vars);
     855                 :             : 
     856                 :             :         /* Sort by name */
     857                 :           7 :         qsort(result, *num_vars,
     858                 :             :                   sizeof(struct config_generic *), guc_var_compare);
     859                 :             : 
     860                 :          14 :         return result;
     861                 :           7 : }
     862                 :             : 
     863                 :             : 
     864                 :             : /*
     865                 :             :  * Build the GUC hash table.  This is split out so that help_config.c can
     866                 :             :  * extract all the variables without running all of InitializeGUCOptions.
     867                 :             :  * It's not meant for use anyplace else.
     868                 :             :  */
     869                 :             : void
     870                 :           6 : build_guc_variables(void)
     871                 :             : {
     872                 :           6 :         int                     size_vars;
     873                 :           6 :         int                     num_vars = 0;
     874                 :           6 :         HASHCTL         hash_ctl;
     875                 :           6 :         GUCHashEntry *hentry;
     876                 :           6 :         bool            found;
     877                 :             : 
     878                 :             :         /*
     879                 :             :          * Create the memory context that will hold all GUC-related data.
     880                 :             :          */
     881         [ +  - ]:           6 :         Assert(GUCMemoryContext == NULL);
     882                 :           6 :         GUCMemoryContext = AllocSetContextCreate(TopMemoryContext,
     883                 :             :                                                                                          "GUCMemoryContext",
     884                 :             :                                                                                          ALLOCSET_DEFAULT_SIZES);
     885                 :             : 
     886                 :             :         /*
     887                 :             :          * Count all the built-in variables.
     888                 :             :          */
     889         [ +  + ]:        2472 :         for (int i = 0; ConfigureNames[i].name; i++)
     890                 :        2466 :                 num_vars++;
     891                 :             : 
     892                 :             :         /*
     893                 :             :          * Create hash table with 20% slack
     894                 :             :          */
     895                 :           6 :         size_vars = num_vars + num_vars / 4;
     896                 :             : 
     897                 :           6 :         hash_ctl.keysize = sizeof(char *);
     898                 :           6 :         hash_ctl.entrysize = sizeof(GUCHashEntry);
     899                 :           6 :         hash_ctl.hash = guc_name_hash;
     900                 :           6 :         hash_ctl.match = guc_name_match;
     901                 :           6 :         hash_ctl.hcxt = GUCMemoryContext;
     902                 :           6 :         guc_hashtab = hash_create("GUC hash table",
     903                 :           6 :                                                           size_vars,
     904                 :             :                                                           &hash_ctl,
     905                 :             :                                                           HASH_ELEM | HASH_FUNCTION | HASH_COMPARE | HASH_CONTEXT);
     906                 :             : 
     907         [ +  + ]:        2472 :         for (int i = 0; ConfigureNames[i].name; i++)
     908                 :             :         {
     909                 :        2466 :                 struct config_generic *gucvar = &ConfigureNames[i];
     910                 :             : 
     911                 :        4932 :                 hentry = (GUCHashEntry *) hash_search(guc_hashtab,
     912                 :        2466 :                                                                                           &gucvar->name,
     913                 :             :                                                                                           HASH_ENTER,
     914                 :             :                                                                                           &found);
     915         [ +  - ]:        2466 :                 Assert(!found);
     916                 :        2466 :                 hentry->gucvar = gucvar;
     917                 :        2466 :         }
     918                 :             : 
     919         [ +  - ]:           6 :         Assert(num_vars == hash_get_num_entries(guc_hashtab));
     920                 :           6 : }
     921                 :             : 
     922                 :             : /*
     923                 :             :  * Add a new GUC variable to the hash of known variables. The
     924                 :             :  * hash is expanded if needed.
     925                 :             :  */
     926                 :             : static bool
     927                 :        2469 : add_guc_variable(struct config_generic *var, int elevel)
     928                 :             : {
     929                 :        2469 :         GUCHashEntry *hentry;
     930                 :        2469 :         bool            found;
     931                 :             : 
     932                 :        4938 :         hentry = (GUCHashEntry *) hash_search(guc_hashtab,
     933                 :        2469 :                                                                                   &var->name,
     934                 :             :                                                                                   HASH_ENTER_NULL,
     935                 :             :                                                                                   &found);
     936         [ -  + ]:        2469 :         if (unlikely(hentry == NULL))
     937                 :             :         {
     938   [ #  #  #  #  :           0 :                 ereport(elevel,
          #  #  #  #  #  
                      # ]
     939                 :             :                                 (errcode(ERRCODE_OUT_OF_MEMORY),
     940                 :             :                                  errmsg("out of memory")));
     941                 :           0 :                 return false;                   /* out of memory */
     942                 :             :         }
     943         [ +  - ]:        2469 :         Assert(!found);
     944                 :        2469 :         hentry->gucvar = var;
     945                 :        2469 :         return true;
     946                 :        2469 : }
     947                 :             : 
     948                 :             : /*
     949                 :             :  * Decide whether a proposed custom variable name is allowed.
     950                 :             :  *
     951                 :             :  * It must be two or more identifiers separated by dots, where the rules
     952                 :             :  * for what is an identifier agree with scan.l.  (If you change this rule,
     953                 :             :  * adjust the errdetail in assignable_custom_variable_name().)
     954                 :             :  */
     955                 :             : static bool
     956                 :          16 : valid_custom_variable_name(const char *name)
     957                 :             : {
     958                 :          16 :         bool            saw_sep = false;
     959                 :          16 :         bool            name_start = true;
     960                 :             : 
     961   [ +  +  +  + ]:         426 :         for (const char *p = name; *p; p++)
     962                 :             :         {
     963         [ +  + ]:         410 :                 if (*p == GUC_QUALIFIER_SEPARATOR)
     964                 :             :                 {
     965         [ +  - ]:          18 :                         if (name_start)
     966                 :           0 :                                 return false;   /* empty name component */
     967                 :          18 :                         saw_sep = true;
     968                 :          18 :                         name_start = true;
     969                 :          18 :                 }
     970                 :         392 :                 else if (strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZ"
     971   [ +  +  +  +  :         784 :                                                 "abcdefghijklmnopqrstuvwxyz_", *p) != NULL ||
                   -  + ]
     972                 :           2 :                                  IS_HIGHBIT_SET(*p))
     973                 :             :                 {
     974                 :             :                         /* okay as first or non-first character */
     975                 :         390 :                         name_start = false;
     976                 :         390 :                 }
     977   [ +  -  +  - ]:           2 :                 else if (!name_start && strchr("0123456789$", *p) != NULL)
     978                 :             :                          /* okay as non-first character */ ;
     979                 :             :                 else
     980                 :           2 :                         return false;
     981                 :         408 :         }
     982         [ -  + ]:          14 :         if (name_start)
     983                 :           0 :                 return false;                   /* empty name component */
     984                 :             :         /* OK if we found at least one separator */
     985                 :          14 :         return saw_sep;
     986                 :          16 : }
     987                 :             : 
     988                 :             : /*
     989                 :             :  * Decide whether an unrecognized variable name is allowed to be SET.
     990                 :             :  *
     991                 :             :  * It must pass the syntactic rules of valid_custom_variable_name(),
     992                 :             :  * and it must not be in any namespace already reserved by an extension.
     993                 :             :  * (We make this separate from valid_custom_variable_name() because we don't
     994                 :             :  * apply the reserved-namespace test when reading configuration files.)
     995                 :             :  *
     996                 :             :  * If valid, return true.  Otherwise, return false if skip_errors is true,
     997                 :             :  * else throw a suitable error at the specified elevel (and return false
     998                 :             :  * if that's less than ERROR).
     999                 :             :  */
    1000                 :             : static bool
    1001                 :          16 : assignable_custom_variable_name(const char *name, bool skip_errors, int elevel)
    1002                 :             : {
    1003                 :             :         /* If there's no separator, it can't be a custom variable */
    1004                 :          16 :         const char *sep = strchr(name, GUC_QUALIFIER_SEPARATOR);
    1005                 :             : 
    1006         [ +  + ]:          16 :         if (sep != NULL)
    1007                 :             :         {
    1008                 :          14 :                 size_t          classLen = sep - name;
    1009                 :          14 :                 ListCell   *lc;
    1010                 :             : 
    1011                 :             :                 /* The name must be syntactically acceptable ... */
    1012         [ +  + ]:          14 :                 if (!valid_custom_variable_name(name))
    1013                 :             :                 {
    1014         [ -  + ]:           4 :                         if (!skip_errors)
    1015   [ -  +  #  #  :           4 :                                 ereport(elevel,
          +  +  #  #  #  
                      # ]
    1016                 :             :                                                 (errcode(ERRCODE_INVALID_NAME),
    1017                 :             :                                                  errmsg("invalid configuration parameter name \"%s\"",
    1018                 :             :                                                                 name),
    1019                 :             :                                                  errdetail("Custom parameter names must be two or more simple identifiers separated by dots.")));
    1020                 :           0 :                         return false;
    1021                 :             :                 }
    1022                 :             :                 /* ... and it must not match any previously-reserved prefix */
    1023   [ +  +  +  +  :          19 :                 foreach(lc, reserved_class_prefix)
             +  +  +  + ]
    1024                 :             :                 {
    1025                 :           9 :                         const char *rcprefix = lfirst(lc);
    1026                 :             : 
    1027   [ +  +  +  + ]:           9 :                         if (strlen(rcprefix) == classLen &&
    1028                 :           1 :                                 strncmp(name, rcprefix, classLen) == 0)
    1029                 :             :                         {
    1030         [ -  + ]:           2 :                                 if (!skip_errors)
    1031   [ -  +  #  #  :           2 :                                         ereport(elevel,
          +  +  #  #  #  
                      # ]
    1032                 :             :                                                         (errcode(ERRCODE_INVALID_NAME),
    1033                 :             :                                                          errmsg("invalid configuration parameter name \"%s\"",
    1034                 :             :                                                                         name),
    1035                 :             :                                                          errdetail("\"%s\" is a reserved prefix.",
    1036                 :             :                                                                            rcprefix)));
    1037                 :           0 :                                 return false;
    1038                 :             :                         }
    1039         [ +  + ]:           9 :                 }
    1040                 :             :                 /* OK to create it */
    1041                 :           9 :                 return true;
    1042                 :          10 :         }
    1043                 :             : 
    1044                 :             :         /* Unrecognized single-part name */
    1045         [ -  + ]:           2 :         if (!skip_errors)
    1046   [ -  +  #  #  :           2 :                 ereport(elevel,
          +  +  #  #  #  
                      # ]
    1047                 :             :                                 (errcode(ERRCODE_UNDEFINED_OBJECT),
    1048                 :             :                                  errmsg("unrecognized configuration parameter \"%s\"",
    1049                 :             :                                                 name)));
    1050                 :           0 :         return false;
    1051                 :          10 : }
    1052                 :             : 
    1053                 :             : /*
    1054                 :             :  * Create and add a placeholder variable for a custom variable name.
    1055                 :             :  */
    1056                 :             : static struct config_generic *
    1057                 :           9 : add_placeholder_variable(const char *name, int elevel)
    1058                 :             : {
    1059                 :           9 :         size_t          sz = sizeof(struct config_generic) + sizeof(char *);
    1060                 :           9 :         struct config_generic *var;
    1061                 :             : 
    1062                 :           9 :         var = (struct config_generic *) guc_malloc(elevel, sz);
    1063         [ +  - ]:           9 :         if (var == NULL)
    1064                 :           0 :                 return NULL;
    1065                 :           9 :         memset(var, 0, sz);
    1066                 :             : 
    1067                 :           9 :         var->name = guc_strdup(elevel, name);
    1068         [ +  - ]:           9 :         if (var->name == NULL)
    1069                 :             :         {
    1070                 :           0 :                 guc_free(var);
    1071                 :           0 :                 return NULL;
    1072                 :             :         }
    1073                 :             : 
    1074                 :           9 :         var->context = PGC_USERSET;
    1075                 :           9 :         var->group = CUSTOM_OPTIONS;
    1076                 :           9 :         var->short_desc = "GUC placeholder variable";
    1077                 :           9 :         var->flags = GUC_NO_SHOW_ALL | GUC_NOT_IN_SAMPLE | GUC_CUSTOM_PLACEHOLDER;
    1078                 :           9 :         var->vartype = PGC_STRING;
    1079                 :             : 
    1080                 :             :         /*
    1081                 :             :          * The char* is allocated at the end of the struct since we have no
    1082                 :             :          * 'static' place to point to.  Note that the current value, as well as
    1083                 :             :          * the boot and reset values, start out NULL.
    1084                 :             :          */
    1085                 :           9 :         var->_string.variable = (char **) (var + 1);
    1086                 :             : 
    1087         [ +  - ]:           9 :         if (!add_guc_variable(var, elevel))
    1088                 :             :         {
    1089                 :           0 :                 guc_free(unconstify(char *, var->name));
    1090                 :           0 :                 guc_free(var);
    1091                 :           0 :                 return NULL;
    1092                 :             :         }
    1093                 :             : 
    1094                 :           9 :         return var;
    1095                 :           9 : }
    1096                 :             : 
    1097                 :             : /*
    1098                 :             :  * Look up option "name".  If it exists, return a pointer to its record.
    1099                 :             :  * Otherwise, if create_placeholders is true and name is a valid-looking
    1100                 :             :  * custom variable name, we'll create and return a placeholder record.
    1101                 :             :  * Otherwise, if skip_errors is true, then we silently return NULL for
    1102                 :             :  * an unrecognized or invalid name.  Otherwise, the error is reported at
    1103                 :             :  * error level elevel (and we return NULL if that's less than ERROR).
    1104                 :             :  *
    1105                 :             :  * Note: internal errors, primarily out-of-memory, draw an elevel-level
    1106                 :             :  * report and NULL return regardless of skip_errors.  Hence, callers must
    1107                 :             :  * handle a NULL return whenever elevel < ERROR, but they should not need
    1108                 :             :  * to emit any additional error message.  (In practice, internal errors
    1109                 :             :  * can only happen when create_placeholders is true, so callers passing
    1110                 :             :  * false need not think terribly hard about this.)
    1111                 :             :  */
    1112                 :             : struct config_generic *
    1113                 :       63692 : find_option(const char *name, bool create_placeholders, bool skip_errors,
    1114                 :             :                         int elevel)
    1115                 :             : {
    1116                 :       63692 :         GUCHashEntry *hentry;
    1117                 :             : 
    1118         [ +  - ]:       63692 :         Assert(name);
    1119                 :             : 
    1120                 :             :         /* Look it up using the hash table. */
    1121                 :       63692 :         hentry = (GUCHashEntry *) hash_search(guc_hashtab,
    1122                 :             :                                                                                   &name,
    1123                 :             :                                                                                   HASH_FIND,
    1124                 :             :                                                                                   NULL);
    1125         [ +  + ]:       63692 :         if (hentry)
    1126                 :       63659 :                 return hentry->gucvar;
    1127                 :             : 
    1128                 :             :         /*
    1129                 :             :          * See if the name is an obsolete name for a variable.  We assume that the
    1130                 :             :          * set of supported old names is short enough that a brute-force search is
    1131                 :             :          * the best way.
    1132                 :             :          */
    1133   [ +  +  +  + ]:         132 :         for (int i = 0; map_old_guc_names[i] != NULL; i += 2)
    1134                 :             :         {
    1135         [ -  + ]:          99 :                 if (guc_name_compare(name, map_old_guc_names[i]) == 0)
    1136                 :           0 :                         return find_option(map_old_guc_names[i + 1], false,
    1137                 :           0 :                                                            skip_errors, elevel);
    1138                 :          99 :         }
    1139                 :             : 
    1140         [ +  + ]:          35 :         if (create_placeholders)
    1141                 :             :         {
    1142                 :             :                 /*
    1143                 :             :                  * Check if the name is valid, and if so, add a placeholder.
    1144                 :             :                  */
    1145         [ +  - ]:           9 :                 if (assignable_custom_variable_name(name, skip_errors, elevel))
    1146                 :           9 :                         return add_placeholder_variable(name, elevel);
    1147                 :             :                 else
    1148                 :           0 :                         return NULL;            /* error message, if any, already emitted */
    1149                 :             :         }
    1150                 :             : 
    1151                 :             :         /* Unknown name and we're not supposed to make a placeholder */
    1152         [ +  + ]:          26 :         if (!skip_errors)
    1153   [ -  +  #  #  :          12 :                 ereport(elevel,
          +  +  #  #  #  
                      # ]
    1154                 :             :                                 (errcode(ERRCODE_UNDEFINED_OBJECT),
    1155                 :             :                                  errmsg("unrecognized configuration parameter \"%s\"",
    1156                 :             :                                                 name)));
    1157                 :          14 :         return NULL;
    1158                 :       63684 : }
    1159                 :             : 
    1160                 :             : 
    1161                 :             : /*
    1162                 :             :  * comparator for qsorting an array of GUC pointers
    1163                 :             :  */
    1164                 :             : static int
    1165                 :       26622 : guc_var_compare(const void *a, const void *b)
    1166                 :             : {
    1167                 :       26622 :         const struct config_generic *ca = *(const struct config_generic *const *) a;
    1168                 :       26622 :         const struct config_generic *cb = *(const struct config_generic *const *) b;
    1169                 :             : 
    1170                 :       53244 :         return guc_name_compare(ca->name, cb->name);
    1171                 :       26622 : }
    1172                 :             : 
    1173                 :             : /*
    1174                 :             :  * the bare comparison function for GUC names
    1175                 :             :  */
    1176                 :             : int
    1177                 :       94011 : guc_name_compare(const char *namea, const char *nameb)
    1178                 :             : {
    1179                 :             :         /*
    1180                 :             :          * The temptation to use strcasecmp() here must be resisted, because the
    1181                 :             :          * hash mapping has to remain stable across setlocale() calls. So, build
    1182                 :             :          * our own with a simple ASCII-only downcasing.
    1183                 :             :          */
    1184   [ +  +  +  + ]:     1110120 :         while (*namea && *nameb)
    1185                 :             :         {
    1186                 :     1046179 :                 char            cha = *namea++;
    1187                 :     1046179 :                 char            chb = *nameb++;
    1188                 :             : 
    1189   [ +  +  +  + ]:     1046179 :                 if (cha >= 'A' && cha <= 'Z')
    1190                 :        7362 :                         cha += 'a' - 'A';
    1191   [ +  +  +  + ]:     1046179 :                 if (chb >= 'A' && chb <= 'Z')
    1192                 :        4968 :                         chb += 'a' - 'A';
    1193         [ +  + ]:     1046179 :                 if (cha != chb)
    1194                 :       30070 :                         return cha - chb;
    1195      [ -  +  + ]:     1046179 :         }
    1196         [ +  + ]:       63941 :         if (*namea)
    1197                 :         140 :                 return 1;                               /* a is longer */
    1198         [ +  + ]:       63801 :         if (*nameb)
    1199                 :         137 :                 return -1;                              /* b is longer */
    1200                 :       63664 :         return 0;
    1201                 :       94011 : }
    1202                 :             : 
    1203                 :             : /*
    1204                 :             :  * Hash function that's compatible with guc_name_compare
    1205                 :             :  */
    1206                 :             : static uint32
    1207                 :       71092 : guc_name_hash(const void *key, Size keysize)
    1208                 :             : {
    1209                 :       71092 :         uint32          result = 0;
    1210                 :       71092 :         const char *name = *(const char *const *) key;
    1211                 :             : 
    1212         [ +  + ]:     1192585 :         while (*name)
    1213                 :             :         {
    1214                 :     1121493 :                 char            ch = *name++;
    1215                 :             : 
    1216                 :             :                 /* Case-fold in the same way as guc_name_compare */
    1217   [ +  +  +  + ]:     1121493 :                 if (ch >= 'A' && ch <= 'Z')
    1218                 :        4840 :                         ch += 'a' - 'A';
    1219                 :             : 
    1220                 :             :                 /* Merge into hash ... not very bright, but it needn't be */
    1221                 :     1121493 :                 result = pg_rotate_left32(result, 5);
    1222                 :     1121493 :                 result ^= (uint32) ch;
    1223                 :     1121493 :         }
    1224                 :      142184 :         return result;
    1225                 :       71092 : }
    1226                 :             : 
    1227                 :             : /*
    1228                 :             :  * Dynahash match function to use in guc_hashtab
    1229                 :             :  */
    1230                 :             : static int
    1231                 :       63664 : guc_name_match(const void *key1, const void *key2, Size keysize)
    1232                 :             : {
    1233                 :       63664 :         const char *name1 = *(const char *const *) key1;
    1234                 :       63664 :         const char *name2 = *(const char *const *) key2;
    1235                 :             : 
    1236                 :      127328 :         return guc_name_compare(name1, name2);
    1237                 :       63664 : }
    1238                 :             : 
    1239                 :             : 
    1240                 :             : /*
    1241                 :             :  * Convert a GUC name to the form that should be used in pg_parameter_acl.
    1242                 :             :  *
    1243                 :             :  * We need to canonicalize entries since, for example, case should not be
    1244                 :             :  * significant.  In addition, we apply the map_old_guc_names[] mapping so that
    1245                 :             :  * any obsolete names will be converted when stored in a new PG version.
    1246                 :             :  * Note however that this function does not verify legality of the name.
    1247                 :             :  *
    1248                 :             :  * The result is a palloc'd string.
    1249                 :             :  */
    1250                 :             : char *
    1251                 :           0 : convert_GUC_name_for_parameter_acl(const char *name)
    1252                 :             : {
    1253                 :           0 :         char       *result;
    1254                 :             : 
    1255                 :             :         /* Apply old-GUC-name mapping. */
    1256         [ #  # ]:           0 :         for (int i = 0; map_old_guc_names[i] != NULL; i += 2)
    1257                 :             :         {
    1258         [ #  # ]:           0 :                 if (guc_name_compare(name, map_old_guc_names[i]) == 0)
    1259                 :             :                 {
    1260                 :           0 :                         name = map_old_guc_names[i + 1];
    1261                 :           0 :                         break;
    1262                 :             :                 }
    1263                 :           0 :         }
    1264                 :             : 
    1265                 :             :         /* Apply case-folding that matches guc_name_compare(). */
    1266                 :           0 :         result = pstrdup(name);
    1267         [ #  # ]:           0 :         for (char *ptr = result; *ptr != '\0'; ptr++)
    1268                 :             :         {
    1269                 :           0 :                 char            ch = *ptr;
    1270                 :             : 
    1271   [ #  #  #  # ]:           0 :                 if (ch >= 'A' && ch <= 'Z')
    1272                 :             :                 {
    1273                 :           0 :                         ch += 'a' - 'A';
    1274                 :           0 :                         *ptr = ch;
    1275                 :           0 :                 }
    1276                 :           0 :         }
    1277                 :             : 
    1278                 :           0 :         return result;
    1279                 :           0 : }
    1280                 :             : 
    1281                 :             : /*
    1282                 :             :  * Check whether we should allow creation of a pg_parameter_acl entry
    1283                 :             :  * for the given name.  (This can be applied either before or after
    1284                 :             :  * canonicalizing it.)  Throws error if not.
    1285                 :             :  */
    1286                 :             : void
    1287                 :           0 : check_GUC_name_for_parameter_acl(const char *name)
    1288                 :             : {
    1289                 :             :         /* OK if the GUC exists. */
    1290         [ #  # ]:           0 :         if (find_option(name, false, true, DEBUG5) != NULL)
    1291                 :           0 :                 return;
    1292                 :             :         /* Otherwise, it'd better be a valid custom GUC name. */
    1293                 :           0 :         (void) assignable_custom_variable_name(name, false, ERROR);
    1294                 :           0 : }
    1295                 :             : 
    1296                 :             : /*
    1297                 :             :  * Routine in charge of checking various states of a GUC.
    1298                 :             :  *
    1299                 :             :  * This performs two sanity checks.  First, it checks that the initial
    1300                 :             :  * value of a GUC is the same when declared and when loaded to prevent
    1301                 :             :  * anybody looking at the C declarations of these GUCs from being fooled by
    1302                 :             :  * mismatched values.  Second, it checks for incorrect flag combinations.
    1303                 :             :  *
    1304                 :             :  * The following validation rules apply for the values:
    1305                 :             :  * bool - can be false, otherwise must be same as the boot_val
    1306                 :             :  * int  - can be 0, otherwise must be same as the boot_val
    1307                 :             :  * real - can be 0.0, otherwise must be same as the boot_val
    1308                 :             :  * string - can be NULL, otherwise must be strcmp equal to the boot_val
    1309                 :             :  * enum - must be same as the boot_val
    1310                 :             :  */
    1311                 :             : #ifdef USE_ASSERT_CHECKING
    1312                 :             : static bool
    1313                 :        4930 : check_GUC_init(const struct config_generic *gconf)
    1314                 :             : {
    1315                 :             :         /* Checks on values */
    1316   [ -  +  +  +  :        4930 :         switch (gconf->vartype)
                   +  + ]
    1317                 :             :         {
    1318                 :             :                 case PGC_BOOL:
    1319                 :             :                         {
    1320                 :        1729 :                                 const struct config_bool *conf = &gconf->_bool;
    1321                 :             : 
    1322   [ +  +  +  - ]:        1729 :                                 if (*conf->variable && !conf->boot_val)
    1323                 :             :                                 {
    1324   [ #  #  #  # ]:           0 :                                         elog(LOG, "GUC (PGC_BOOL) %s, boot_val=%d, C-var=%d",
    1325                 :             :                                                  gconf->name, conf->boot_val, *conf->variable);
    1326                 :           0 :                                         return false;
    1327                 :             :                                 }
    1328                 :        1729 :                                 break;
    1329                 :        1729 :                         }
    1330                 :             :                 case PGC_INT:
    1331                 :             :                         {
    1332                 :         914 :                                 const struct config_int *conf = &gconf->_int;
    1333                 :             : 
    1334   [ +  +  +  - ]:         914 :                                 if (*conf->variable != 0 && *conf->variable != conf->boot_val)
    1335                 :             :                                 {
    1336   [ #  #  #  # ]:           0 :                                         elog(LOG, "GUC (PGC_INT) %s, boot_val=%d, C-var=%d",
    1337                 :             :                                                  gconf->name, conf->boot_val, *conf->variable);
    1338                 :           0 :                                         return false;
    1339                 :             :                                 }
    1340                 :         914 :                                 break;
    1341                 :         914 :                         }
    1342                 :             :                 case PGC_REAL:
    1343                 :             :                         {
    1344                 :         162 :                                 const struct config_real *conf = &gconf->_real;
    1345                 :             : 
    1346   [ +  +  +  - ]:         162 :                                 if (*conf->variable != 0.0 && *conf->variable != conf->boot_val)
    1347                 :             :                                 {
    1348   [ #  #  #  # ]:           0 :                                         elog(LOG, "GUC (PGC_REAL) %s, boot_val=%g, C-var=%g",
    1349                 :             :                                                  gconf->name, conf->boot_val, *conf->variable);
    1350                 :           0 :                                         return false;
    1351                 :             :                                 }
    1352                 :         162 :                                 break;
    1353                 :         162 :                         }
    1354                 :             :                 case PGC_STRING:
    1355                 :             :                         {
    1356                 :        1407 :                                 const struct config_string *conf = &gconf->_string;
    1357                 :             : 
    1358   [ +  +  -  + ]:        1431 :                                 if (*conf->variable != NULL &&
    1359         [ +  - ]:          24 :                                         (conf->boot_val == NULL ||
    1360                 :          24 :                                          strcmp(*conf->variable, conf->boot_val) != 0))
    1361                 :             :                                 {
    1362   [ #  #  #  #  :           0 :                                         elog(LOG, "GUC (PGC_STRING) %s, boot_val=%s, C-var=%s",
                   #  # ]
    1363                 :             :                                                  gconf->name, conf->boot_val ? conf->boot_val : "<null>", *conf->variable);
    1364                 :           0 :                                         return false;
    1365                 :             :                                 }
    1366                 :        1407 :                                 break;
    1367         [ +  + ]:        1407 :                         }
    1368                 :             :                 case PGC_ENUM:
    1369                 :             :                         {
    1370                 :         718 :                                 const struct config_enum *conf = &gconf->_enum;
    1371                 :             : 
    1372         [ -  + ]:         718 :                                 if (*conf->variable != conf->boot_val)
    1373                 :             :                                 {
    1374   [ #  #  #  # ]:           0 :                                         elog(LOG, "GUC (PGC_ENUM) %s, boot_val=%d, C-var=%d",
    1375                 :             :                                                  gconf->name, conf->boot_val, *conf->variable);
    1376                 :           0 :                                         return false;
    1377                 :             :                                 }
    1378                 :         718 :                                 break;
    1379                 :         718 :                         }
    1380                 :             :         }
    1381                 :             : 
    1382                 :             :         /* Flag combinations */
    1383                 :             : 
    1384                 :             :         /*
    1385                 :             :          * GUC_NO_SHOW_ALL requires GUC_NOT_IN_SAMPLE, as a parameter not part of
    1386                 :             :          * SHOW ALL should not be hidden in postgresql.conf.sample.
    1387                 :             :          */
    1388   [ +  +  +  - ]:        4930 :         if ((gconf->flags & GUC_NO_SHOW_ALL) &&
    1389                 :          36 :                 !(gconf->flags & GUC_NOT_IN_SAMPLE))
    1390                 :             :         {
    1391   [ #  #  #  # ]:           0 :                 elog(LOG, "GUC %s flags: NO_SHOW_ALL and !NOT_IN_SAMPLE",
    1392                 :             :                          gconf->name);
    1393                 :           0 :                 return false;
    1394                 :             :         }
    1395                 :             : 
    1396                 :        4930 :         return true;
    1397                 :       11976 : }
    1398                 :             : #endif
    1399                 :             : 
    1400                 :             : /*
    1401                 :             :  * Initialize GUC options during program startup.
    1402                 :             :  *
    1403                 :             :  * Note that we cannot read the config file yet, since we have not yet
    1404                 :             :  * processed command-line switches.
    1405                 :             :  */
    1406                 :             : void
    1407                 :           6 : InitializeGUCOptions(void)
    1408                 :             : {
    1409                 :           6 :         HASH_SEQ_STATUS status;
    1410                 :           6 :         GUCHashEntry *hentry;
    1411                 :             : 
    1412                 :             :         /*
    1413                 :             :          * Before log_line_prefix could possibly receive a nonempty setting, make
    1414                 :             :          * sure that timezone processing is minimally alive (see elog.c).
    1415                 :             :          */
    1416                 :           6 :         pg_timezone_initialize();
    1417                 :             : 
    1418                 :             :         /*
    1419                 :             :          * Create GUCMemoryContext and build hash table of all GUC variables.
    1420                 :             :          */
    1421                 :           6 :         build_guc_variables();
    1422                 :             : 
    1423                 :             :         /*
    1424                 :             :          * Load all variables with their compiled-in defaults, and initialize
    1425                 :             :          * status fields as needed.
    1426                 :             :          */
    1427                 :           6 :         hash_seq_init(&status, guc_hashtab);
    1428         [ +  + ]:        2472 :         while ((hentry = (GUCHashEntry *) hash_seq_search(&status)) != NULL)
    1429                 :             :         {
    1430                 :             :                 /* Check mapping between initial and default value */
    1431         [ +  - ]:        2466 :                 Assert(check_GUC_init(hentry->gucvar));
    1432                 :             : 
    1433                 :        2466 :                 InitializeOneGUCOption(hentry->gucvar);
    1434                 :             :         }
    1435                 :             : 
    1436                 :           6 :         reporting_enabled = false;
    1437                 :             : 
    1438                 :             :         /*
    1439                 :             :          * Prevent any attempt to override the transaction modes from
    1440                 :             :          * non-interactive sources.
    1441                 :             :          */
    1442                 :           6 :         SetConfigOption("transaction_isolation", "read committed",
    1443                 :             :                                         PGC_POSTMASTER, PGC_S_OVERRIDE);
    1444                 :           6 :         SetConfigOption("transaction_read_only", "no",
    1445                 :             :                                         PGC_POSTMASTER, PGC_S_OVERRIDE);
    1446                 :           6 :         SetConfigOption("transaction_deferrable", "no",
    1447                 :             :                                         PGC_POSTMASTER, PGC_S_OVERRIDE);
    1448                 :             : 
    1449                 :             :         /*
    1450                 :             :          * For historical reasons, some GUC parameters can receive defaults from
    1451                 :             :          * environment variables.  Process those settings.
    1452                 :             :          */
    1453                 :           6 :         InitializeGUCOptionsFromEnvironment();
    1454                 :           6 : }
    1455                 :             : 
    1456                 :             : /*
    1457                 :             :  * Assign any GUC values that can come from the server's environment.
    1458                 :             :  *
    1459                 :             :  * This is called from InitializeGUCOptions, and also from ProcessConfigFile
    1460                 :             :  * to deal with the possibility that a setting has been removed from
    1461                 :             :  * postgresql.conf and should now get a value from the environment.
    1462                 :             :  * (The latter is a kludge that should probably go away someday; if so,
    1463                 :             :  * fold this back into InitializeGUCOptions.)
    1464                 :             :  */
    1465                 :             : static void
    1466                 :           6 : InitializeGUCOptionsFromEnvironment(void)
    1467                 :             : {
    1468                 :           6 :         char       *env;
    1469                 :           6 :         ssize_t         stack_rlimit;
    1470                 :             : 
    1471                 :           6 :         env = getenv("PGPORT");
    1472         [ +  + ]:           6 :         if (env != NULL)
    1473                 :           2 :                 SetConfigOption("port", env, PGC_POSTMASTER, PGC_S_ENV_VAR);
    1474                 :             : 
    1475                 :           6 :         env = getenv("PGDATESTYLE");
    1476         [ +  + ]:           6 :         if (env != NULL)
    1477                 :           1 :                 SetConfigOption("datestyle", env, PGC_POSTMASTER, PGC_S_ENV_VAR);
    1478                 :             : 
    1479                 :           6 :         env = getenv("PGCLIENTENCODING");
    1480         [ +  - ]:           6 :         if (env != NULL)
    1481                 :           0 :                 SetConfigOption("client_encoding", env, PGC_POSTMASTER, PGC_S_ENV_VAR);
    1482                 :             : 
    1483                 :             :         /*
    1484                 :             :          * rlimit isn't exactly an "environment variable", but it behaves about
    1485                 :             :          * the same.  If we can identify the platform stack depth rlimit, increase
    1486                 :             :          * default stack depth setting up to whatever is safe (but at most 2MB).
    1487                 :             :          * Report the value's source as PGC_S_DYNAMIC_DEFAULT if it's 2MB, or as
    1488                 :             :          * PGC_S_ENV_VAR if it's reflecting the rlimit limit.
    1489                 :             :          */
    1490                 :           6 :         stack_rlimit = get_stack_depth_rlimit();
    1491         [ -  + ]:           6 :         if (stack_rlimit > 0)
    1492                 :             :         {
    1493                 :           6 :                 ssize_t         new_limit = (stack_rlimit - STACK_DEPTH_SLOP) / 1024;
    1494                 :             : 
    1495         [ -  + ]:           6 :                 if (new_limit > 100)
    1496                 :             :                 {
    1497                 :           6 :                         GucSource       source;
    1498                 :           6 :                         char            limbuf[16];
    1499                 :             : 
    1500         [ -  + ]:           6 :                         if (new_limit < 2048)
    1501                 :           0 :                                 source = PGC_S_ENV_VAR;
    1502                 :             :                         else
    1503                 :             :                         {
    1504                 :           6 :                                 new_limit = 2048;
    1505                 :           6 :                                 source = PGC_S_DYNAMIC_DEFAULT;
    1506                 :             :                         }
    1507                 :           6 :                         snprintf(limbuf, sizeof(limbuf), "%zd", new_limit);
    1508                 :          12 :                         SetConfigOption("max_stack_depth", limbuf,
    1509                 :           6 :                                                         PGC_POSTMASTER, source);
    1510                 :           6 :                 }
    1511                 :           6 :         }
    1512                 :           6 : }
    1513                 :             : 
    1514                 :             : /*
    1515                 :             :  * Initialize one GUC option variable to its compiled-in default.
    1516                 :             :  *
    1517                 :             :  * Note: the reason for calling check_hooks is not that we think the boot_val
    1518                 :             :  * might fail, but that the hooks might wish to compute an "extra" struct.
    1519                 :             :  */
    1520                 :             : static void
    1521                 :       17800 : InitializeOneGUCOption(struct config_generic *gconf)
    1522                 :             : {
    1523                 :       17800 :         void       *extra = NULL;
    1524                 :             : 
    1525                 :       17800 :         gconf->status = 0;
    1526                 :       17800 :         gconf->source = PGC_S_DEFAULT;
    1527                 :       17800 :         gconf->reset_source = PGC_S_DEFAULT;
    1528                 :       17800 :         gconf->scontext = PGC_INTERNAL;
    1529                 :       17800 :         gconf->reset_scontext = PGC_INTERNAL;
    1530                 :       17800 :         gconf->srole = BOOTSTRAP_SUPERUSERID;
    1531                 :       17800 :         gconf->reset_srole = BOOTSTRAP_SUPERUSERID;
    1532                 :       17800 :         gconf->stack = NULL;
    1533                 :       17800 :         gconf->extra = NULL;
    1534                 :       17800 :         gconf->last_reported = NULL;
    1535                 :       17800 :         gconf->sourcefile = NULL;
    1536                 :       17800 :         gconf->sourceline = 0;
    1537                 :             : 
    1538   [ -  +  +  +  :       17800 :         switch (gconf->vartype)
                   +  + ]
    1539                 :             :         {
    1540                 :             :                 case PGC_BOOL:
    1541                 :             :                         {
    1542                 :        5062 :                                 struct config_bool *conf = &gconf->_bool;
    1543                 :        5062 :                                 bool            newval = conf->boot_val;
    1544                 :             : 
    1545         [ +  - ]:        5062 :                                 if (!call_bool_check_hook(gconf, &newval, &extra,
    1546                 :             :                                                                                   PGC_S_DEFAULT, LOG))
    1547   [ #  #  #  # ]:           0 :                                         elog(FATAL, "failed to initialize %s to %d",
    1548                 :             :                                                  gconf->name, (int) newval);
    1549         [ +  - ]:        5062 :                                 if (conf->assign_hook)
    1550                 :           0 :                                         conf->assign_hook(newval, extra);
    1551                 :        5062 :                                 *conf->variable = conf->reset_val = newval;
    1552                 :             :                                 break;
    1553                 :        5062 :                         }
    1554                 :             :                 case PGC_INT:
    1555                 :             :                         {
    1556                 :        3302 :                                 struct config_int *conf = &gconf->_int;
    1557                 :        3302 :                                 int                     newval = conf->boot_val;
    1558                 :             : 
    1559         [ +  - ]:        3302 :                                 Assert(newval >= conf->min);
    1560         [ +  - ]:        3302 :                                 Assert(newval <= conf->max);
    1561         [ +  - ]:        3302 :                                 if (!call_int_check_hook(gconf, &newval, &extra,
    1562                 :             :                                                                                  PGC_S_DEFAULT, LOG))
    1563   [ #  #  #  # ]:           0 :                                         elog(FATAL, "failed to initialize %s to %d",
    1564                 :             :                                                  gconf->name, newval);
    1565         [ +  + ]:        3302 :                                 if (conf->assign_hook)
    1566                 :        1014 :                                         conf->assign_hook(newval, extra);
    1567                 :        3302 :                                 *conf->variable = conf->reset_val = newval;
    1568                 :             :                                 break;
    1569                 :        3302 :                         }
    1570                 :             :                 case PGC_REAL:
    1571                 :             :                         {
    1572                 :         162 :                                 struct config_real *conf = &gconf->_real;
    1573                 :         162 :                                 double          newval = conf->boot_val;
    1574                 :             : 
    1575         [ +  - ]:         162 :                                 Assert(newval >= conf->min);
    1576         [ +  - ]:         162 :                                 Assert(newval <= conf->max);
    1577         [ +  - ]:         162 :                                 if (!call_real_check_hook(gconf, &newval, &extra,
    1578                 :             :                                                                                   PGC_S_DEFAULT, LOG))
    1579   [ #  #  #  # ]:           0 :                                         elog(FATAL, "failed to initialize %s to %g",
    1580                 :             :                                                  gconf->name, newval);
    1581         [ +  + ]:         162 :                                 if (conf->assign_hook)
    1582                 :          12 :                                         conf->assign_hook(newval, extra);
    1583                 :         162 :                                 *conf->variable = conf->reset_val = newval;
    1584                 :             :                                 break;
    1585                 :         162 :                         }
    1586                 :             :                 case PGC_STRING:
    1587                 :             :                         {
    1588                 :        7128 :                                 struct config_string *conf = &gconf->_string;
    1589                 :        7128 :                                 char       *newval;
    1590                 :             : 
    1591                 :             :                                 /* non-NULL boot_val must always get strdup'd */
    1592         [ +  + ]:        7128 :                                 if (conf->boot_val != NULL)
    1593                 :        6122 :                                         newval = guc_strdup(FATAL, conf->boot_val);
    1594                 :             :                                 else
    1595                 :        1006 :                                         newval = NULL;
    1596                 :             : 
    1597         [ +  - ]:        7128 :                                 if (!call_string_check_hook(gconf, &newval, &extra,
    1598                 :             :                                                                                         PGC_S_DEFAULT, LOG))
    1599   [ #  #  #  #  :           0 :                                         elog(FATAL, "failed to initialize %s to \"%s\"",
                   #  # ]
    1600                 :             :                                                  gconf->name, newval ? newval : "");
    1601         [ +  + ]:        7128 :                                 if (conf->assign_hook)
    1602                 :        5900 :                                         conf->assign_hook(newval, extra);
    1603                 :        7128 :                                 *conf->variable = conf->reset_val = newval;
    1604                 :             :                                 break;
    1605                 :        7128 :                         }
    1606                 :             :                 case PGC_ENUM:
    1607                 :             :                         {
    1608                 :        2146 :                                 struct config_enum *conf = &gconf->_enum;
    1609                 :        2146 :                                 int                     newval = conf->boot_val;
    1610                 :             : 
    1611         [ +  - ]:        2146 :                                 if (!call_enum_check_hook(gconf, &newval, &extra,
    1612                 :             :                                                                                   PGC_S_DEFAULT, LOG))
    1613   [ #  #  #  # ]:           0 :                                         elog(FATAL, "failed to initialize %s to %d",
    1614                 :             :                                                  gconf->name, newval);
    1615         [ +  + ]:        2146 :                                 if (conf->assign_hook)
    1616                 :          42 :                                         conf->assign_hook(newval, extra);
    1617                 :        2146 :                                 *conf->variable = conf->reset_val = newval;
    1618                 :             :                                 break;
    1619                 :        2146 :                         }
    1620                 :             :         }
    1621                 :             : 
    1622                 :       17800 :         gconf->extra = gconf->reset_extra = extra;
    1623                 :       17800 : }
    1624                 :             : 
    1625                 :             : /*
    1626                 :             :  * Summarily remove a GUC variable from any linked lists it's in.
    1627                 :             :  *
    1628                 :             :  * We use this in cases where the variable is about to be deleted or reset.
    1629                 :             :  * These aren't common operations, so it's okay if this is a bit slow.
    1630                 :             :  */
    1631                 :             : static void
    1632                 :       12875 : RemoveGUCFromLists(struct config_generic *gconf)
    1633                 :             : {
    1634         [ -  + ]:       12875 :         if (gconf->source != PGC_S_DEFAULT)
    1635                 :       12875 :                 dlist_delete(&gconf->nondef_link);
    1636         [ +  - ]:       12875 :         if (gconf->stack != NULL)
    1637                 :           0 :                 slist_delete(&guc_stack_list, &gconf->stack_link);
    1638         [ +  + ]:       12875 :         if (gconf->status & GUC_NEEDS_REPORT)
    1639                 :        1431 :                 slist_delete(&guc_report_list, &gconf->report_link);
    1640                 :       12875 : }
    1641                 :             : 
    1642                 :             : 
    1643                 :             : /*
    1644                 :             :  * Select the configuration files and data directory to be used, and
    1645                 :             :  * do the initial read of postgresql.conf.
    1646                 :             :  *
    1647                 :             :  * This is called after processing command-line switches.
    1648                 :             :  *              userDoption is the -D switch value if any (NULL if unspecified).
    1649                 :             :  *              progname is just for use in error messages.
    1650                 :             :  *
    1651                 :             :  * Returns true on success; on failure, prints a suitable error message
    1652                 :             :  * to stderr and returns false.
    1653                 :             :  */
    1654                 :             : bool
    1655                 :           6 : SelectConfigFiles(const char *userDoption, const char *progname)
    1656                 :             : {
    1657                 :           6 :         char       *configdir;
    1658                 :           6 :         char       *fname;
    1659                 :           6 :         bool            fname_is_malloced;
    1660                 :           6 :         struct stat stat_buf;
    1661                 :           6 :         struct config_generic *data_directory_rec;
    1662                 :             : 
    1663                 :             :         /* configdir is -D option, or $PGDATA if no -D */
    1664         [ +  + ]:           6 :         if (userDoption)
    1665                 :           2 :                 configdir = make_absolute_path(userDoption);
    1666                 :             :         else
    1667                 :           4 :                 configdir = make_absolute_path(getenv("PGDATA"));
    1668                 :             : 
    1669   [ +  -  +  - ]:           6 :         if (configdir && stat(configdir, &stat_buf) != 0)
    1670                 :             :         {
    1671                 :           0 :                 write_stderr("%s: could not access directory \"%s\": %m\n",
    1672                 :           0 :                                          progname,
    1673                 :           0 :                                          configdir);
    1674         [ #  # ]:           0 :                 if (errno == ENOENT)
    1675                 :           0 :                         write_stderr("Run initdb or pg_basebackup to initialize a PostgreSQL data directory.\n");
    1676                 :           0 :                 goto fail;
    1677                 :             :         }
    1678                 :             : 
    1679                 :             :         /*
    1680                 :             :          * Find the configuration file: if config_file was specified on the
    1681                 :             :          * command line, use it, else use configdir/postgresql.conf.  In any case
    1682                 :             :          * ensure the result is an absolute path, so that it will be interpreted
    1683                 :             :          * the same way by future backends.
    1684                 :             :          */
    1685         [ -  + ]:           6 :         if (ConfigFileName)
    1686                 :             :         {
    1687                 :           0 :                 fname = make_absolute_path(ConfigFileName);
    1688                 :           0 :                 fname_is_malloced = true;
    1689                 :           0 :         }
    1690         [ +  - ]:           6 :         else if (configdir)
    1691                 :             :         {
    1692                 :           6 :                 fname = guc_malloc(FATAL,
    1693                 :           6 :                                                    strlen(configdir) + strlen(CONFIG_FILENAME) + 2);
    1694                 :           6 :                 sprintf(fname, "%s/%s", configdir, CONFIG_FILENAME);
    1695                 :           6 :                 fname_is_malloced = false;
    1696                 :           6 :         }
    1697                 :             :         else
    1698                 :             :         {
    1699                 :           0 :                 write_stderr("%s does not know where to find the server configuration file.\n"
    1700                 :             :                                          "You must specify the --config-file or -D invocation "
    1701                 :             :                                          "option or set the PGDATA environment variable.\n",
    1702                 :           0 :                                          progname);
    1703                 :           0 :                 goto fail;
    1704                 :             :         }
    1705                 :             : 
    1706                 :             :         /*
    1707                 :             :          * Set the ConfigFileName GUC variable to its final value, ensuring that
    1708                 :             :          * it can't be overridden later.
    1709                 :             :          */
    1710                 :           6 :         SetConfigOption("config_file", fname, PGC_POSTMASTER, PGC_S_OVERRIDE);
    1711                 :             : 
    1712         [ -  + ]:           6 :         if (fname_is_malloced)
    1713                 :           0 :                 free(fname);
    1714                 :             :         else
    1715                 :           6 :                 guc_free(fname);
    1716                 :             : 
    1717                 :             :         /*
    1718                 :             :          * Now read the config file for the first time.
    1719                 :             :          */
    1720         [ -  + ]:           6 :         if (stat(ConfigFileName, &stat_buf) != 0)
    1721                 :             :         {
    1722                 :           0 :                 write_stderr("%s: could not access the server configuration file \"%s\": %m\n",
    1723                 :           0 :                                          progname, ConfigFileName);
    1724                 :           0 :                 goto fail;
    1725                 :             :         }
    1726                 :             : 
    1727                 :             :         /*
    1728                 :             :          * Read the configuration file for the first time.  This time only the
    1729                 :             :          * data_directory parameter is picked up to determine the data directory,
    1730                 :             :          * so that we can read the PG_AUTOCONF_FILENAME file next time.
    1731                 :             :          */
    1732                 :           6 :         ProcessConfigFile(PGC_POSTMASTER);
    1733                 :             : 
    1734                 :             :         /*
    1735                 :             :          * If the data_directory GUC variable has been set, use that as DataDir;
    1736                 :             :          * otherwise use configdir if set; else punt.
    1737                 :             :          *
    1738                 :             :          * Note: SetDataDir will copy and absolute-ize its argument, so we don't
    1739                 :             :          * have to.
    1740                 :             :          */
    1741                 :           6 :         data_directory_rec =
    1742                 :           6 :                 find_option("data_directory", false, false, PANIC);
    1743         [ -  + ]:           6 :         if (*data_directory_rec->_string.variable)
    1744                 :           0 :                 SetDataDir(*data_directory_rec->_string.variable);
    1745         [ +  - ]:           6 :         else if (configdir)
    1746                 :           6 :                 SetDataDir(configdir);
    1747                 :             :         else
    1748                 :             :         {
    1749                 :           0 :                 write_stderr("%s does not know where to find the database system data.\n"
    1750                 :             :                                          "This can be specified as \"data_directory\" in \"%s\", "
    1751                 :             :                                          "or by the -D invocation option, or by the "
    1752                 :             :                                          "PGDATA environment variable.\n",
    1753                 :           0 :                                          progname, ConfigFileName);
    1754                 :           0 :                 goto fail;
    1755                 :             :         }
    1756                 :             : 
    1757                 :             :         /*
    1758                 :             :          * Reflect the final DataDir value back into the data_directory GUC var.
    1759                 :             :          * (If you are wondering why we don't just make them a single variable,
    1760                 :             :          * it's because the EXEC_BACKEND case needs DataDir to be transmitted to
    1761                 :             :          * child backends specially.  XXX is that still true?  Given that we now
    1762                 :             :          * chdir to DataDir, EXEC_BACKEND can read the config file without knowing
    1763                 :             :          * DataDir in advance.)
    1764                 :             :          */
    1765                 :           6 :         SetConfigOption("data_directory", DataDir, PGC_POSTMASTER, PGC_S_OVERRIDE);
    1766                 :             : 
    1767                 :             :         /*
    1768                 :             :          * Now read the config file a second time, allowing any settings in the
    1769                 :             :          * PG_AUTOCONF_FILENAME file to take effect.  (This is pretty ugly, but
    1770                 :             :          * since we have to determine the DataDir before we can find the autoconf
    1771                 :             :          * file, the alternatives seem worse.)
    1772                 :             :          */
    1773                 :           6 :         ProcessConfigFile(PGC_POSTMASTER);
    1774                 :             : 
    1775                 :             :         /*
    1776                 :             :          * If timezone_abbreviations wasn't set in the configuration file, install
    1777                 :             :          * the default value.  We do it this way because we can't safely install a
    1778                 :             :          * "real" value until my_exec_path is set, which may not have happened
    1779                 :             :          * when InitializeGUCOptions runs, so the bootstrap default value cannot
    1780                 :             :          * be the real desired default.
    1781                 :             :          */
    1782                 :           6 :         pg_timezone_abbrev_initialize();
    1783                 :             : 
    1784                 :             :         /*
    1785                 :             :          * Figure out where pg_hba.conf is, and make sure the path is absolute.
    1786                 :             :          */
    1787         [ -  + ]:           6 :         if (HbaFileName)
    1788                 :             :         {
    1789                 :           0 :                 fname = make_absolute_path(HbaFileName);
    1790                 :           0 :                 fname_is_malloced = true;
    1791                 :           0 :         }
    1792         [ +  - ]:           6 :         else if (configdir)
    1793                 :             :         {
    1794                 :           6 :                 fname = guc_malloc(FATAL,
    1795                 :           6 :                                                    strlen(configdir) + strlen(HBA_FILENAME) + 2);
    1796                 :           6 :                 sprintf(fname, "%s/%s", configdir, HBA_FILENAME);
    1797                 :           6 :                 fname_is_malloced = false;
    1798                 :           6 :         }
    1799                 :             :         else
    1800                 :             :         {
    1801                 :           0 :                 write_stderr("%s does not know where to find the \"hba\" configuration file.\n"
    1802                 :             :                                          "This can be specified as \"hba_file\" in \"%s\", "
    1803                 :             :                                          "or by the -D invocation option, or by the "
    1804                 :             :                                          "PGDATA environment variable.\n",
    1805                 :           0 :                                          progname, ConfigFileName);
    1806                 :           0 :                 goto fail;
    1807                 :             :         }
    1808                 :           6 :         SetConfigOption("hba_file", fname, PGC_POSTMASTER, PGC_S_OVERRIDE);
    1809                 :             : 
    1810         [ -  + ]:           6 :         if (fname_is_malloced)
    1811                 :           0 :                 free(fname);
    1812                 :             :         else
    1813                 :           6 :                 guc_free(fname);
    1814                 :             : 
    1815                 :             :         /*
    1816                 :             :          * Likewise for pg_ident.conf.
    1817                 :             :          */
    1818         [ -  + ]:           6 :         if (IdentFileName)
    1819                 :             :         {
    1820                 :           0 :                 fname = make_absolute_path(IdentFileName);
    1821                 :           0 :                 fname_is_malloced = true;
    1822                 :           0 :         }
    1823         [ +  - ]:           6 :         else if (configdir)
    1824                 :             :         {
    1825                 :           6 :                 fname = guc_malloc(FATAL,
    1826                 :           6 :                                                    strlen(configdir) + strlen(IDENT_FILENAME) + 2);
    1827                 :           6 :                 sprintf(fname, "%s/%s", configdir, IDENT_FILENAME);
    1828                 :           6 :                 fname_is_malloced = false;
    1829                 :           6 :         }
    1830                 :             :         else
    1831                 :             :         {
    1832                 :           0 :                 write_stderr("%s does not know where to find the \"ident\" configuration file.\n"
    1833                 :             :                                          "This can be specified as \"ident_file\" in \"%s\", "
    1834                 :             :                                          "or by the -D invocation option, or by the "
    1835                 :             :                                          "PGDATA environment variable.\n",
    1836                 :           0 :                                          progname, ConfigFileName);
    1837                 :           0 :                 goto fail;
    1838                 :             :         }
    1839                 :           6 :         SetConfigOption("ident_file", fname, PGC_POSTMASTER, PGC_S_OVERRIDE);
    1840                 :             : 
    1841         [ -  + ]:           6 :         if (fname_is_malloced)
    1842                 :           0 :                 free(fname);
    1843                 :             :         else
    1844                 :           6 :                 guc_free(fname);
    1845                 :             : 
    1846                 :           6 :         free(configdir);
    1847                 :             : 
    1848                 :           6 :         return true;
    1849                 :             : 
    1850                 :             : fail:
    1851                 :           0 :         free(configdir);
    1852                 :             : 
    1853                 :           0 :         return false;
    1854                 :           6 : }
    1855                 :             : 
    1856                 :             : /*
    1857                 :             :  * pg_timezone_abbrev_initialize --- set default value if not done already
    1858                 :             :  *
    1859                 :             :  * This is called after initial loading of postgresql.conf.  If no
    1860                 :             :  * timezone_abbreviations setting was found therein, select default.
    1861                 :             :  * If a non-default value is already installed, nothing will happen.
    1862                 :             :  *
    1863                 :             :  * This can also be called from ProcessConfigFile to establish the default
    1864                 :             :  * value after a postgresql.conf entry for it is removed.
    1865                 :             :  */
    1866                 :             : static void
    1867                 :           6 : pg_timezone_abbrev_initialize(void)
    1868                 :             : {
    1869                 :           6 :         SetConfigOption("timezone_abbreviations", "Default",
    1870                 :             :                                         PGC_POSTMASTER, PGC_S_DYNAMIC_DEFAULT);
    1871                 :           6 : }
    1872                 :             : 
    1873                 :             : 
    1874                 :             : /*
    1875                 :             :  * Reset all options to their saved default values (implements RESET ALL)
    1876                 :             :  */
    1877                 :             : void
    1878                 :           1 : ResetAllOptions(void)
    1879                 :             : {
    1880                 :           1 :         dlist_mutable_iter iter;
    1881                 :             : 
    1882                 :             :         /* We need only consider GUCs not already at PGC_S_DEFAULT */
    1883   [ +  -  +  + ]:          61 :         dlist_foreach_modify(iter, &guc_nondef_list)
    1884                 :             :         {
    1885                 :          60 :                 struct config_generic *gconf = dlist_container(struct config_generic,
    1886                 :             :                                                                                                            nondef_link, iter.cur);
    1887                 :             : 
    1888                 :             :                 /* Don't reset non-SET-able values */
    1889   [ +  +  +  + ]:          60 :                 if (gconf->context != PGC_SUSET &&
    1890                 :          54 :                         gconf->context != PGC_USERSET)
    1891                 :          34 :                         continue;
    1892                 :             :                 /* Don't reset if special exclusion from RESET ALL */
    1893         [ +  + ]:          26 :                 if (gconf->flags & GUC_NO_RESET_ALL)
    1894                 :           5 :                         continue;
    1895                 :             :                 /* No need to reset if wasn't SET */
    1896         [ +  + ]:          21 :                 if (gconf->source <= PGC_S_OVERRIDE)
    1897                 :          19 :                         continue;
    1898                 :             : 
    1899                 :             :                 /* Save old value to support transaction abort */
    1900                 :           2 :                 push_old_value(gconf, GUC_ACTION_SET);
    1901                 :             : 
    1902   [ -  -  +  +  :           2 :                 switch (gconf->vartype)
                   -  - ]
    1903                 :             :                 {
    1904                 :             :                         case PGC_BOOL:
    1905                 :             :                                 {
    1906                 :           0 :                                         struct config_bool *conf = &gconf->_bool;
    1907                 :             : 
    1908         [ #  # ]:           0 :                                         if (conf->assign_hook)
    1909                 :           0 :                                                 conf->assign_hook(conf->reset_val,
    1910                 :           0 :                                                                                   gconf->reset_extra);
    1911                 :           0 :                                         *conf->variable = conf->reset_val;
    1912                 :           0 :                                         set_extra_field(gconf, &gconf->extra,
    1913                 :           0 :                                                                         gconf->reset_extra);
    1914                 :             :                                         break;
    1915                 :           0 :                                 }
    1916                 :             :                         case PGC_INT:
    1917                 :             :                                 {
    1918                 :           0 :                                         struct config_int *conf = &gconf->_int;
    1919                 :             : 
    1920         [ #  # ]:           0 :                                         if (conf->assign_hook)
    1921                 :           0 :                                                 conf->assign_hook(conf->reset_val,
    1922                 :           0 :                                                                                   gconf->reset_extra);
    1923                 :           0 :                                         *conf->variable = conf->reset_val;
    1924                 :           0 :                                         set_extra_field(gconf, &gconf->extra,
    1925                 :           0 :                                                                         gconf->reset_extra);
    1926                 :             :                                         break;
    1927                 :           0 :                                 }
    1928                 :             :                         case PGC_REAL:
    1929                 :             :                                 {
    1930                 :           1 :                                         struct config_real *conf = &gconf->_real;
    1931                 :             : 
    1932         [ -  + ]:           1 :                                         if (conf->assign_hook)
    1933                 :           0 :                                                 conf->assign_hook(conf->reset_val,
    1934                 :           0 :                                                                                   gconf->reset_extra);
    1935                 :           1 :                                         *conf->variable = conf->reset_val;
    1936                 :           2 :                                         set_extra_field(gconf, &gconf->extra,
    1937                 :           1 :                                                                         gconf->reset_extra);
    1938                 :             :                                         break;
    1939                 :           1 :                                 }
    1940                 :             :                         case PGC_STRING:
    1941                 :             :                                 {
    1942                 :           1 :                                         struct config_string *conf = &gconf->_string;
    1943                 :             : 
    1944         [ -  + ]:           1 :                                         if (conf->assign_hook)
    1945                 :           0 :                                                 conf->assign_hook(conf->reset_val,
    1946                 :           0 :                                                                                   gconf->reset_extra);
    1947                 :           1 :                                         set_string_field(gconf, conf->variable, conf->reset_val);
    1948                 :           2 :                                         set_extra_field(gconf, &gconf->extra,
    1949                 :           1 :                                                                         gconf->reset_extra);
    1950                 :             :                                         break;
    1951                 :           1 :                                 }
    1952                 :             :                         case PGC_ENUM:
    1953                 :             :                                 {
    1954                 :           0 :                                         struct config_enum *conf = &gconf->_enum;
    1955                 :             : 
    1956         [ #  # ]:           0 :                                         if (conf->assign_hook)
    1957                 :           0 :                                                 conf->assign_hook(conf->reset_val,
    1958                 :           0 :                                                                                   gconf->reset_extra);
    1959                 :           0 :                                         *conf->variable = conf->reset_val;
    1960                 :           0 :                                         set_extra_field(gconf, &gconf->extra,
    1961                 :           0 :                                                                         gconf->reset_extra);
    1962                 :             :                                         break;
    1963                 :           0 :                                 }
    1964                 :             :                 }
    1965                 :             : 
    1966                 :           2 :                 set_guc_source(gconf, gconf->reset_source);
    1967                 :           2 :                 gconf->scontext = gconf->reset_scontext;
    1968                 :           2 :                 gconf->srole = gconf->reset_srole;
    1969                 :             : 
    1970   [ -  +  #  # ]:           2 :                 if ((gconf->flags & GUC_REPORT) && !(gconf->status & GUC_NEEDS_REPORT))
    1971                 :             :                 {
    1972                 :           0 :                         gconf->status |= GUC_NEEDS_REPORT;
    1973                 :           0 :                         slist_push_head(&guc_report_list, &gconf->report_link);
    1974                 :           0 :                 }
    1975      [ -  +  + ]:          60 :         }
    1976                 :           1 : }
    1977                 :             : 
    1978                 :             : 
    1979                 :             : /*
    1980                 :             :  * Apply a change to a GUC variable's "source" field.
    1981                 :             :  *
    1982                 :             :  * Use this rather than just assigning, to ensure that the variable's
    1983                 :             :  * membership in guc_nondef_list is updated correctly.
    1984                 :             :  */
    1985                 :             : static void
    1986                 :       63482 : set_guc_source(struct config_generic *gconf, GucSource newsource)
    1987                 :             : {
    1988                 :             :         /* Adjust nondef list membership if appropriate for change */
    1989         [ +  + ]:       63482 :         if (gconf->source == PGC_S_DEFAULT)
    1990                 :             :         {
    1991         [ +  + ]:       32745 :                 if (newsource != PGC_S_DEFAULT)
    1992                 :       32726 :                         dlist_push_tail(&guc_nondef_list, &gconf->nondef_link);
    1993                 :       32745 :         }
    1994                 :             :         else
    1995                 :             :         {
    1996         [ +  + ]:       30737 :                 if (newsource == PGC_S_DEFAULT)
    1997                 :        9695 :                         dlist_delete(&gconf->nondef_link);
    1998                 :             :         }
    1999                 :             :         /* Now update the source field */
    2000                 :       63482 :         gconf->source = newsource;
    2001                 :       63482 : }
    2002                 :             : 
    2003                 :             : 
    2004                 :             : /*
    2005                 :             :  * push_old_value
    2006                 :             :  *              Push previous state during transactional assignment to a GUC variable.
    2007                 :             :  */
    2008                 :             : static void
    2009                 :       22295 : push_old_value(struct config_generic *gconf, GucAction action)
    2010                 :             : {
    2011                 :       22295 :         GucStack   *stack;
    2012                 :             : 
    2013                 :             :         /* If we're not inside a nest level, do nothing */
    2014         [ +  - ]:       22295 :         if (GUCNestLevel == 0)
    2015                 :           0 :                 return;
    2016                 :             : 
    2017                 :             :         /* Do we already have a stack entry of the current nest level? */
    2018                 :       22295 :         stack = gconf->stack;
    2019   [ +  +  +  + ]:       22295 :         if (stack && stack->nest_level >= GUCNestLevel)
    2020                 :             :         {
    2021                 :             :                 /* Yes, so adjust its state if necessary */
    2022         [ +  - ]:        1911 :                 Assert(stack->nest_level == GUCNestLevel);
    2023   [ +  -  +  - ]:        1911 :                 switch (action)
    2024                 :             :                 {
    2025                 :             :                         case GUC_ACTION_SET:
    2026                 :             :                                 /* SET overrides any prior action at same nest level */
    2027         [ +  - ]:        1829 :                                 if (stack->state == GUC_SET_LOCAL)
    2028                 :             :                                 {
    2029                 :             :                                         /* must discard old masked value */
    2030                 :           0 :                                         discard_stack_value(gconf, &stack->masked);
    2031                 :           0 :                                 }
    2032                 :        1829 :                                 stack->state = GUC_SET;
    2033                 :        1829 :                                 break;
    2034                 :             :                         case GUC_ACTION_LOCAL:
    2035         [ +  + ]:          82 :                                 if (stack->state == GUC_SET)
    2036                 :             :                                 {
    2037                 :             :                                         /* SET followed by SET LOCAL, remember SET's value */
    2038                 :           2 :                                         stack->masked_scontext = gconf->scontext;
    2039                 :           2 :                                         stack->masked_srole = gconf->srole;
    2040                 :           2 :                                         set_stack_value(gconf, &stack->masked);
    2041                 :           2 :                                         stack->state = GUC_SET_LOCAL;
    2042                 :           2 :                                 }
    2043                 :             :                                 /* in all other cases, no change to stack entry */
    2044                 :          82 :                                 break;
    2045                 :             :                         case GUC_ACTION_SAVE:
    2046                 :             :                                 /* Could only have a prior SAVE of same variable */
    2047         [ #  # ]:           0 :                                 Assert(stack->state == GUC_SAVE);
    2048                 :           0 :                                 break;
    2049                 :             :                 }
    2050                 :        1911 :                 return;
    2051                 :             :         }
    2052                 :             : 
    2053                 :             :         /*
    2054                 :             :          * Push a new stack entry
    2055                 :             :          *
    2056                 :             :          * We keep all the stack entries in TopTransactionContext for simplicity.
    2057                 :             :          */
    2058                 :       20384 :         stack = (GucStack *) MemoryContextAllocZero(TopTransactionContext,
    2059                 :             :                                                                                                 sizeof(GucStack));
    2060                 :             : 
    2061                 :       20384 :         stack->prev = gconf->stack;
    2062                 :       20384 :         stack->nest_level = GUCNestLevel;
    2063   [ +  -  +  + ]:       20384 :         switch (action)
    2064                 :             :         {
    2065                 :             :                 case GUC_ACTION_SET:
    2066                 :        6328 :                         stack->state = GUC_SET;
    2067                 :        6328 :                         break;
    2068                 :             :                 case GUC_ACTION_LOCAL:
    2069                 :         293 :                         stack->state = GUC_LOCAL;
    2070                 :         293 :                         break;
    2071                 :             :                 case GUC_ACTION_SAVE:
    2072                 :       13763 :                         stack->state = GUC_SAVE;
    2073                 :       13763 :                         break;
    2074                 :             :         }
    2075                 :       20384 :         stack->source = gconf->source;
    2076                 :       20384 :         stack->scontext = gconf->scontext;
    2077                 :       20384 :         stack->srole = gconf->srole;
    2078                 :       20384 :         set_stack_value(gconf, &stack->prior);
    2079                 :             : 
    2080         [ +  + ]:       20384 :         if (gconf->stack == NULL)
    2081                 :       16895 :                 slist_push_head(&guc_stack_list, &gconf->stack_link);
    2082                 :       20384 :         gconf->stack = stack;
    2083         [ -  + ]:       22295 : }
    2084                 :             : 
    2085                 :             : 
    2086                 :             : /*
    2087                 :             :  * Do GUC processing at main transaction start.
    2088                 :             :  */
    2089                 :             : void
    2090                 :       57914 : AtStart_GUC(void)
    2091                 :             : {
    2092                 :             :         /*
    2093                 :             :          * The nest level should be 0 between transactions; if it isn't, somebody
    2094                 :             :          * didn't call AtEOXact_GUC, or called it with the wrong nestLevel.  We
    2095                 :             :          * throw a warning but make no other effort to clean up.
    2096                 :             :          */
    2097         [ +  - ]:       57914 :         if (GUCNestLevel != 0)
    2098   [ #  #  #  # ]:           0 :                 elog(WARNING, "GUC nest level = %d at transaction start",
    2099                 :             :                          GUCNestLevel);
    2100                 :       57914 :         GUCNestLevel = 1;
    2101                 :       57914 : }
    2102                 :             : 
    2103                 :             : /*
    2104                 :             :  * Enter a new nesting level for GUC values.  This is called at subtransaction
    2105                 :             :  * start, and when entering a function that has proconfig settings, and in
    2106                 :             :  * some other places where we want to set GUC variables transiently.
    2107                 :             :  * NOTE we must not risk error here, else subtransaction start will be unhappy.
    2108                 :             :  */
    2109                 :             : int
    2110                 :       15833 : NewGUCNestLevel(void)
    2111                 :             : {
    2112                 :       15833 :         return ++GUCNestLevel;
    2113                 :             : }
    2114                 :             : 
    2115                 :             : /*
    2116                 :             :  * Set search_path to a fixed value for maintenance operations. No effect
    2117                 :             :  * during bootstrap, when the search_path is already set to a fixed value and
    2118                 :             :  * cannot be changed.
    2119                 :             :  */
    2120                 :             : void
    2121                 :       13891 : RestrictSearchPath(void)
    2122                 :             : {
    2123         [ +  + ]:       13891 :         if (!IsBootstrapProcessingMode())
    2124                 :       13279 :                 set_config_option("search_path", GUC_SAFE_SEARCH_PATH, PGC_USERSET,
    2125                 :             :                                                   PGC_S_SESSION, GUC_ACTION_SAVE, true, 0, false);
    2126                 :       13891 : }
    2127                 :             : 
    2128                 :             : /*
    2129                 :             :  * Do GUC processing at transaction or subtransaction commit or abort, or
    2130                 :             :  * when exiting a function that has proconfig settings, or when undoing a
    2131                 :             :  * transient assignment to some GUC variables.  (The name is thus a bit of
    2132                 :             :  * a misnomer; perhaps it should be ExitGUCNestLevel or some such.)
    2133                 :             :  * During abort, we discard all GUC settings that were applied at nesting
    2134                 :             :  * levels >= nestLevel.  nestLevel == 1 corresponds to the main transaction.
    2135                 :             :  */
    2136                 :             : void
    2137                 :       73517 : AtEOXact_GUC(bool isCommit, int nestLevel)
    2138                 :             : {
    2139                 :       73517 :         slist_mutable_iter iter;
    2140                 :             : 
    2141                 :             :         /*
    2142                 :             :          * Note: it's possible to get here with GUCNestLevel == nestLevel-1 during
    2143                 :             :          * abort, if there is a failure during transaction start before
    2144                 :             :          * AtStart_GUC is called.
    2145                 :             :          */
    2146   [ +  -  +  - ]:       73517 :         Assert(nestLevel > 0 &&
    2147                 :             :                    (nestLevel <= GUCNestLevel ||
    2148                 :             :                         (nestLevel == GUCNestLevel + 1 && !isCommit)));
    2149                 :             : 
    2150                 :             :         /* We need only process GUCs having nonempty stacks */
    2151   [ +  +  +  +  :       94862 :         slist_foreach_modify(iter, &guc_stack_list)
                   +  + ]
    2152                 :             :         {
    2153                 :       21345 :                 struct config_generic *gconf = slist_container(struct config_generic,
    2154                 :             :                                                                                                            stack_link, iter.cur);
    2155                 :       21345 :                 GucStack   *stack;
    2156                 :             : 
    2157                 :             :                 /*
    2158                 :             :                  * Process and pop each stack entry within the nest level. To simplify
    2159                 :             :                  * fmgr_security_definer() and other places that use GUC_ACTION_SAVE,
    2160                 :             :                  * we allow failure exit from code that uses a local nest level to be
    2161                 :             :                  * recovered at the surrounding transaction or subtransaction abort;
    2162                 :             :                  * so there could be more than one stack entry to pop.
    2163                 :             :                  */
    2164   [ +  +  +  + ]:       66577 :                 while ((stack = gconf->stack) != NULL &&
    2165                 :       24841 :                            stack->nest_level >= nestLevel)
    2166                 :             :                 {
    2167                 :       20391 :                         GucStack   *prev = stack->prev;
    2168                 :       20391 :                         bool            restorePrior = false;
    2169                 :       20391 :                         bool            restoreMasked = false;
    2170                 :       20391 :                         bool            changed;
    2171                 :             : 
    2172                 :             :                         /*
    2173                 :             :                          * In this next bit, if we don't set either restorePrior or
    2174                 :             :                          * restoreMasked, we must "discard" any unwanted fields of the
    2175                 :             :                          * stack entries to avoid leaking memory.  If we do set one of
    2176                 :             :                          * those flags, unused fields will be cleaned up after restoring.
    2177                 :             :                          */
    2178         [ +  + ]:       20391 :                         if (!isCommit)          /* if abort, always restore prior value */
    2179                 :       13747 :                                 restorePrior = true;
    2180         [ +  + ]:        6644 :                         else if (stack->state == GUC_SAVE)
    2181                 :         353 :                                 restorePrior = true;
    2182         [ +  + ]:        6291 :                         else if (stack->nest_level == 1)
    2183                 :             :                         {
    2184                 :             :                                 /* transaction commit */
    2185         [ +  + ]:        6283 :                                 if (stack->state == GUC_SET_LOCAL)
    2186                 :           2 :                                         restoreMasked = true;
    2187         [ +  + ]:        6281 :                                 else if (stack->state == GUC_SET)
    2188                 :             :                                 {
    2189                 :             :                                         /* we keep the current active value */
    2190                 :        6163 :                                         discard_stack_value(gconf, &stack->prior);
    2191                 :        6163 :                                 }
    2192                 :             :                                 else                    /* must be GUC_LOCAL */
    2193                 :         118 :                                         restorePrior = true;
    2194                 :        6283 :                         }
    2195   [ +  +  +  + ]:           8 :                         else if (prev == NULL ||
    2196                 :           2 :                                          prev->nest_level < stack->nest_level - 1)
    2197                 :             :                         {
    2198                 :             :                                 /* decrement entry's level and do not pop it */
    2199                 :           7 :                                 stack->nest_level--;
    2200                 :           7 :                                 continue;
    2201                 :             :                         }
    2202                 :             :                         else
    2203                 :             :                         {
    2204                 :             :                                 /*
    2205                 :             :                                  * We have to merge this stack entry into prev. See README for
    2206                 :             :                                  * discussion of this bit.
    2207                 :             :                                  */
    2208   [ -  +  -  -  :           1 :                                 switch (stack->state)
                      - ]
    2209                 :             :                                 {
    2210                 :             :                                         case GUC_SAVE:
    2211                 :           0 :                                                 Assert(false);  /* can't get here */
    2212                 :           0 :                                                 break;
    2213                 :             : 
    2214                 :             :                                         case GUC_SET:
    2215                 :             :                                                 /* next level always becomes SET */
    2216                 :           1 :                                                 discard_stack_value(gconf, &stack->prior);
    2217         [ +  - ]:           1 :                                                 if (prev->state == GUC_SET_LOCAL)
    2218                 :           0 :                                                         discard_stack_value(gconf, &prev->masked);
    2219                 :           1 :                                                 prev->state = GUC_SET;
    2220                 :           1 :                                                 break;
    2221                 :             : 
    2222                 :             :                                         case GUC_LOCAL:
    2223         [ #  # ]:           0 :                                                 if (prev->state == GUC_SET)
    2224                 :             :                                                 {
    2225                 :             :                                                         /* LOCAL migrates down */
    2226                 :           0 :                                                         prev->masked_scontext = stack->scontext;
    2227                 :           0 :                                                         prev->masked_srole = stack->srole;
    2228                 :           0 :                                                         prev->masked = stack->prior;
    2229                 :           0 :                                                         prev->state = GUC_SET_LOCAL;
    2230                 :           0 :                                                 }
    2231                 :             :                                                 else
    2232                 :             :                                                 {
    2233                 :             :                                                         /* else just forget this stack level */
    2234                 :           0 :                                                         discard_stack_value(gconf, &stack->prior);
    2235                 :             :                                                 }
    2236                 :           0 :                                                 break;
    2237                 :             : 
    2238                 :             :                                         case GUC_SET_LOCAL:
    2239                 :             :                                                 /* prior state at this level no longer wanted */
    2240                 :           0 :                                                 discard_stack_value(gconf, &stack->prior);
    2241                 :             :                                                 /* copy down the masked state */
    2242                 :           0 :                                                 prev->masked_scontext = stack->masked_scontext;
    2243                 :           0 :                                                 prev->masked_srole = stack->masked_srole;
    2244         [ #  # ]:           0 :                                                 if (prev->state == GUC_SET_LOCAL)
    2245                 :           0 :                                                         discard_stack_value(gconf, &prev->masked);
    2246                 :           0 :                                                 prev->masked = stack->masked;
    2247                 :           0 :                                                 prev->state = GUC_SET_LOCAL;
    2248                 :           0 :                                                 break;
    2249                 :             :                                 }
    2250                 :             :                         }
    2251                 :             : 
    2252                 :       20384 :                         changed = false;
    2253                 :             : 
    2254   [ +  +  +  + ]:       20384 :                         if (restorePrior || restoreMasked)
    2255                 :             :                         {
    2256                 :             :                                 /* Perform appropriate restoration of the stacked value */
    2257                 :       14220 :                                 config_var_value newvalue;
    2258                 :       14220 :                                 GucSource       newsource;
    2259                 :       14220 :                                 GucContext      newscontext;
    2260                 :       14220 :                                 Oid                     newsrole;
    2261                 :             : 
    2262         [ +  + ]:       14220 :                                 if (restoreMasked)
    2263                 :             :                                 {
    2264                 :           2 :                                         newvalue = stack->masked;
    2265                 :           2 :                                         newsource = PGC_S_SESSION;
    2266                 :           2 :                                         newscontext = stack->masked_scontext;
    2267                 :           2 :                                         newsrole = stack->masked_srole;
    2268                 :           2 :                                 }
    2269                 :             :                                 else
    2270                 :             :                                 {
    2271                 :       14218 :                                         newvalue = stack->prior;
    2272                 :       14218 :                                         newsource = stack->source;
    2273                 :       14218 :                                         newscontext = stack->scontext;
    2274                 :       14218 :                                         newsrole = stack->srole;
    2275                 :             :                                 }
    2276                 :             : 
    2277   [ +  +  +  +  :       14220 :                                 switch (gconf->vartype)
                   -  + ]
    2278                 :             :                                 {
    2279                 :             :                                         case PGC_BOOL:
    2280                 :             :                                                 {
    2281                 :         155 :                                                         struct config_bool *conf = &gconf->_bool;
    2282                 :         155 :                                                         bool            newval = newvalue.val.boolval;
    2283                 :         155 :                                                         void       *newextra = newvalue.extra;
    2284                 :             : 
    2285   [ +  +  -  + ]:         155 :                                                         if (*conf->variable != newval ||
    2286                 :          31 :                                                                 gconf->extra != newextra)
    2287                 :             :                                                         {
    2288         [ -  + ]:         124 :                                                                 if (conf->assign_hook)
    2289                 :           0 :                                                                         conf->assign_hook(newval, newextra);
    2290                 :         124 :                                                                 *conf->variable = newval;
    2291                 :         248 :                                                                 set_extra_field(gconf, &gconf->extra,
    2292                 :         124 :                                                                                                 newextra);
    2293                 :         124 :                                                                 changed = true;
    2294                 :         124 :                                                         }
    2295                 :             :                                                         break;
    2296                 :         155 :                                                 }
    2297                 :             :                                         case PGC_INT:
    2298                 :             :                                                 {
    2299                 :         217 :                                                         struct config_int *conf = &gconf->_int;
    2300                 :         217 :                                                         int                     newval = newvalue.val.intval;
    2301                 :         217 :                                                         void       *newextra = newvalue.extra;
    2302                 :             : 
    2303   [ +  +  -  + ]:         217 :                                                         if (*conf->variable != newval ||
    2304                 :          32 :                                                                 gconf->extra != newextra)
    2305                 :             :                                                         {
    2306         [ +  - ]:         185 :                                                                 if (conf->assign_hook)
    2307                 :           0 :                                                                         conf->assign_hook(newval, newextra);
    2308                 :         185 :                                                                 *conf->variable = newval;
    2309                 :         370 :                                                                 set_extra_field(gconf, &gconf->extra,
    2310                 :         185 :                                                                                                 newextra);
    2311                 :         185 :                                                                 changed = true;
    2312                 :         185 :                                                         }
    2313                 :             :                                                         break;
    2314                 :         217 :                                                 }
    2315                 :             :                                         case PGC_REAL:
    2316                 :             :                                                 {
    2317                 :         183 :                                                         struct config_real *conf = &gconf->_real;
    2318                 :         183 :                                                         double          newval = newvalue.val.realval;
    2319                 :         183 :                                                         void       *newextra = newvalue.extra;
    2320                 :             : 
    2321   [ +  +  -  + ]:         183 :                                                         if (*conf->variable != newval ||
    2322                 :           4 :                                                                 gconf->extra != newextra)
    2323                 :             :                                                         {
    2324         [ -  + ]:         179 :                                                                 if (conf->assign_hook)
    2325                 :           0 :                                                                         conf->assign_hook(newval, newextra);
    2326                 :         179 :                                                                 *conf->variable = newval;
    2327                 :         358 :                                                                 set_extra_field(gconf, &gconf->extra,
    2328                 :         179 :                                                                                                 newextra);
    2329                 :         179 :                                                                 changed = true;
    2330                 :         179 :                                                         }
    2331                 :             :                                                         break;
    2332                 :         183 :                                                 }
    2333                 :             :                                         case PGC_STRING:
    2334                 :             :                                                 {
    2335                 :       13606 :                                                         struct config_string *conf = &gconf->_string;
    2336                 :       13606 :                                                         char       *newval = newvalue.val.stringval;
    2337                 :       13606 :                                                         void       *newextra = newvalue.extra;
    2338                 :             : 
    2339   [ +  +  -  + ]:       13606 :                                                         if (*conf->variable != newval ||
    2340                 :           3 :                                                                 gconf->extra != newextra)
    2341                 :             :                                                         {
    2342         [ +  + ]:       13603 :                                                                 if (conf->assign_hook)
    2343                 :       13485 :                                                                         conf->assign_hook(newval, newextra);
    2344                 :       13603 :                                                                 set_string_field(gconf, conf->variable, newval);
    2345                 :       27206 :                                                                 set_extra_field(gconf, &gconf->extra,
    2346                 :       13603 :                                                                                                 newextra);
    2347                 :       13603 :                                                                 changed = true;
    2348                 :       13603 :                                                         }
    2349                 :             : 
    2350                 :             :                                                         /*
    2351                 :             :                                                          * Release stacked values if not used anymore. We
    2352                 :             :                                                          * could use discard_stack_value() here, but since
    2353                 :             :                                                          * we have type-specific code anyway, might as
    2354                 :             :                                                          * well inline it.
    2355                 :             :                                                          */
    2356                 :       13606 :                                                         set_string_field(gconf, &stack->prior.val.stringval, NULL);
    2357                 :       13606 :                                                         set_string_field(gconf, &stack->masked.val.stringval, NULL);
    2358                 :             :                                                         break;
    2359                 :       13606 :                                                 }
    2360                 :             :                                         case PGC_ENUM:
    2361                 :             :                                                 {
    2362                 :          59 :                                                         struct config_enum *conf = &gconf->_enum;
    2363                 :          59 :                                                         int                     newval = newvalue.val.enumval;
    2364                 :          59 :                                                         void       *newextra = newvalue.extra;
    2365                 :             : 
    2366   [ +  +  -  + ]:          59 :                                                         if (*conf->variable != newval ||
    2367                 :           5 :                                                                 gconf->extra != newextra)
    2368                 :             :                                                         {
    2369         [ +  + ]:          54 :                                                                 if (conf->assign_hook)
    2370                 :           5 :                                                                         conf->assign_hook(newval, newextra);
    2371                 :          54 :                                                                 *conf->variable = newval;
    2372                 :         108 :                                                                 set_extra_field(gconf, &gconf->extra,
    2373                 :          54 :                                                                                                 newextra);
    2374                 :          54 :                                                                 changed = true;
    2375                 :          54 :                                                         }
    2376                 :             :                                                         break;
    2377                 :          59 :                                                 }
    2378                 :             :                                 }
    2379                 :             : 
    2380                 :             :                                 /*
    2381                 :             :                                  * Release stacked extra values if not used anymore.
    2382                 :             :                                  */
    2383                 :       14220 :                                 set_extra_field(gconf, &(stack->prior.extra), NULL);
    2384                 :       14220 :                                 set_extra_field(gconf, &(stack->masked.extra), NULL);
    2385                 :             : 
    2386                 :             :                                 /* And restore source information */
    2387                 :       14220 :                                 set_guc_source(gconf, newsource);
    2388                 :       14220 :                                 gconf->scontext = newscontext;
    2389                 :       14220 :                                 gconf->srole = newsrole;
    2390                 :       14220 :                         }
    2391                 :             : 
    2392                 :             :                         /*
    2393                 :             :                          * Pop the GUC's state stack; if it's now empty, remove the GUC
    2394                 :             :                          * from guc_stack_list.
    2395                 :             :                          */
    2396                 :       20384 :                         gconf->stack = prev;
    2397         [ +  + ]:       20384 :                         if (prev == NULL)
    2398                 :       16895 :                                 slist_delete_current(&iter);
    2399                 :       20384 :                         pfree(stack);
    2400                 :             : 
    2401                 :             :                         /* Report new value if we changed it */
    2402   [ +  +  +  +  :       20384 :                         if (changed && (gconf->flags & GUC_REPORT) &&
                   +  + ]
    2403                 :       13449 :                                 !(gconf->status & GUC_NEEDS_REPORT))
    2404                 :             :                         {
    2405                 :          43 :                                 gconf->status |= GUC_NEEDS_REPORT;
    2406                 :          43 :                                 slist_push_head(&guc_report_list, &gconf->report_link);
    2407                 :          43 :                         }
    2408      [ -  +  + ]:       20391 :                 }                                               /* end of stack-popping loop */
    2409                 :       21345 :         }
    2410                 :             : 
    2411                 :             :         /* Update nesting level */
    2412                 :       73517 :         GUCNestLevel = nestLevel - 1;
    2413                 :       73517 : }
    2414                 :             : 
    2415                 :             : 
    2416                 :             : /*
    2417                 :             :  * Start up automatic reporting of changes to variables marked GUC_REPORT.
    2418                 :             :  * This is executed at completion of backend startup.
    2419                 :             :  */
    2420                 :             : void
    2421                 :         316 : BeginReportingGUCOptions(void)
    2422                 :             : {
    2423                 :         316 :         HASH_SEQ_STATUS status;
    2424                 :         316 :         GUCHashEntry *hentry;
    2425                 :             : 
    2426                 :             :         /*
    2427                 :             :          * Don't do anything unless talking to an interactive frontend.
    2428                 :             :          */
    2429         [ +  + ]:         316 :         if (whereToSendOutput != DestRemote)
    2430                 :           1 :                 return;
    2431                 :             : 
    2432                 :         315 :         reporting_enabled = true;
    2433                 :             : 
    2434                 :             :         /*
    2435                 :             :          * Hack for in_hot_standby: set the GUC value true if appropriate.  This
    2436                 :             :          * is kind of an ugly place to do it, but there's few better options.
    2437                 :             :          *
    2438                 :             :          * (This could be out of date by the time we actually send it, in which
    2439                 :             :          * case the next ReportChangedGUCOptions call will send a duplicate
    2440                 :             :          * report.)
    2441                 :             :          */
    2442         [ +  - ]:         315 :         if (RecoveryInProgress())
    2443                 :           0 :                 SetConfigOption("in_hot_standby", "true",
    2444                 :             :                                                 PGC_INTERNAL, PGC_S_OVERRIDE);
    2445                 :             : 
    2446                 :             :         /* Transmit initial values of interesting variables */
    2447                 :         315 :         hash_seq_init(&status, guc_hashtab);
    2448         [ +  + ]:      132212 :         while ((hentry = (GUCHashEntry *) hash_seq_search(&status)) != NULL)
    2449                 :             :         {
    2450                 :      131897 :                 struct config_generic *conf = hentry->gucvar;
    2451                 :             : 
    2452         [ +  + ]:      131897 :                 if (conf->flags & GUC_REPORT)
    2453                 :        4725 :                         ReportGUCOption(conf);
    2454                 :      131897 :         }
    2455         [ -  + ]:         316 : }
    2456                 :             : 
    2457                 :             : /*
    2458                 :             :  * ReportChangedGUCOptions: report recently-changed GUC_REPORT variables
    2459                 :             :  *
    2460                 :             :  * This is called just before we wait for a new client query.
    2461                 :             :  *
    2462                 :             :  * By handling things this way, we ensure that a ParameterStatus message
    2463                 :             :  * is sent at most once per variable per query, even if the variable
    2464                 :             :  * changed multiple times within the query.  That's quite possible when
    2465                 :             :  * using features such as function SET clauses.  Function SET clauses
    2466                 :             :  * also tend to cause values to change intraquery but eventually revert
    2467                 :             :  * to their prevailing values; ReportGUCOption is responsible for avoiding
    2468                 :             :  * redundant reports in such cases.
    2469                 :             :  */
    2470                 :             : void
    2471                 :       59326 : ReportChangedGUCOptions(void)
    2472                 :             : {
    2473                 :       59326 :         slist_mutable_iter iter;
    2474                 :             : 
    2475                 :             :         /* Quick exit if not (yet) enabled */
    2476         [ +  + ]:       59326 :         if (!reporting_enabled)
    2477                 :         738 :                 return;
    2478                 :             : 
    2479                 :             :         /*
    2480                 :             :          * Since in_hot_standby isn't actually changed by normal GUC actions, we
    2481                 :             :          * need a hack to check whether a new value needs to be reported to the
    2482                 :             :          * client.  For speed, we rely on the assumption that it can never
    2483                 :             :          * transition from false to true.
    2484                 :             :          */
    2485   [ -  +  #  # ]:       58588 :         if (in_hot_standby_guc && !RecoveryInProgress())
    2486                 :           0 :                 SetConfigOption("in_hot_standby", "false",
    2487                 :             :                                                 PGC_INTERNAL, PGC_S_OVERRIDE);
    2488                 :             : 
    2489                 :             :         /* Transmit new values of interesting variables */
    2490   [ +  +  +  +  :       66634 :         slist_foreach_modify(iter, &guc_report_list)
                   +  + ]
    2491                 :             :         {
    2492                 :        8046 :                 struct config_generic *conf = slist_container(struct config_generic,
    2493                 :             :                                                                                                           report_link, iter.cur);
    2494                 :             : 
    2495         [ +  - ]:        8046 :                 Assert((conf->flags & GUC_REPORT) && (conf->status & GUC_NEEDS_REPORT));
    2496                 :        8046 :                 ReportGUCOption(conf);
    2497                 :        8046 :                 conf->status &= ~GUC_NEEDS_REPORT;
    2498                 :        8046 :                 slist_delete_current(&iter);
    2499                 :        8046 :         }
    2500         [ -  + ]:       59326 : }
    2501                 :             : 
    2502                 :             : /*
    2503                 :             :  * ReportGUCOption: if appropriate, transmit option value to frontend
    2504                 :             :  *
    2505                 :             :  * We need not transmit the value if it's the same as what we last
    2506                 :             :  * transmitted.
    2507                 :             :  */
    2508                 :             : static void
    2509                 :       12771 : ReportGUCOption(struct config_generic *record)
    2510                 :             : {
    2511                 :       12771 :         char       *val = ShowGUCOption(record, false);
    2512                 :             : 
    2513   [ +  +  +  + ]:       12771 :         if (record->last_reported == NULL ||
    2514                 :        8046 :                 strcmp(val, record->last_reported) != 0)
    2515                 :             :         {
    2516                 :        6017 :                 StringInfoData msgbuf;
    2517                 :             : 
    2518                 :        6017 :                 pq_beginmessage(&msgbuf, PqMsg_ParameterStatus);
    2519                 :        6017 :                 pq_sendstring(&msgbuf, record->name);
    2520                 :        6017 :                 pq_sendstring(&msgbuf, val);
    2521                 :        6017 :                 pq_endmessage(&msgbuf);
    2522                 :             : 
    2523                 :             :                 /*
    2524                 :             :                  * We need a long-lifespan copy.  If guc_strdup() fails due to OOM,
    2525                 :             :                  * we'll set last_reported to NULL and thereby possibly make a
    2526                 :             :                  * duplicate report later.
    2527                 :             :                  */
    2528                 :        6017 :                 guc_free(record->last_reported);
    2529                 :        6017 :                 record->last_reported = guc_strdup(LOG, val);
    2530                 :        6017 :         }
    2531                 :             : 
    2532                 :       12771 :         pfree(val);
    2533                 :       12771 : }
    2534                 :             : 
    2535                 :             : /*
    2536                 :             :  * Convert a value from one of the human-friendly units ("kB", "min" etc.)
    2537                 :             :  * to the given base unit.  'value' and 'unit' are the input value and unit
    2538                 :             :  * to convert from (there can be trailing spaces in the unit string).
    2539                 :             :  * The converted value is stored in *base_value.
    2540                 :             :  * It's caller's responsibility to round off the converted value as necessary
    2541                 :             :  * and check for out-of-range.
    2542                 :             :  *
    2543                 :             :  * Returns true on success, false if the input unit is not recognized.
    2544                 :             :  */
    2545                 :             : static bool
    2546                 :          92 : convert_to_base_unit(double value, const char *unit,
    2547                 :             :                                          int base_unit, double *base_value)
    2548                 :             : {
    2549                 :          92 :         char            unitstr[MAX_UNIT_LEN + 1];
    2550                 :          92 :         int                     unitlen;
    2551                 :          92 :         const unit_conversion *table;
    2552                 :             : 
    2553                 :             :         /* extract unit string to compare to table entries */
    2554                 :          92 :         unitlen = 0;
    2555   [ +  +  -  +  :         365 :         while (*unit != '\0' && !isspace((unsigned char) *unit) &&
                   +  + ]
    2556                 :         181 :                    unitlen < MAX_UNIT_LEN)
    2557                 :         181 :                 unitstr[unitlen++] = *(unit++);
    2558                 :          92 :         unitstr[unitlen] = '\0';
    2559                 :             :         /* allow whitespace after unit */
    2560         [ -  + ]:          92 :         while (isspace((unsigned char) *unit))
    2561                 :           0 :                 unit++;
    2562         [ -  + ]:          92 :         if (*unit != '\0')
    2563                 :           0 :                 return false;                   /* unit too long, or garbage after it */
    2564                 :             : 
    2565                 :             :         /* now search the appropriate table */
    2566         [ +  + ]:          92 :         if (base_unit & GUC_UNIT_MEMORY)
    2567                 :          86 :                 table = memory_unit_conversion_table;
    2568                 :             :         else
    2569                 :           6 :                 table = time_unit_conversion_table;
    2570                 :             : 
    2571   [ +  -  +  - ]:         976 :         for (int i = 0; *table[i].unit; i++)
    2572                 :             :         {
    2573   [ +  +  +  + ]:         884 :                 if (base_unit == table[i].base_unit &&
    2574                 :         314 :                         strcmp(unitstr, table[i].unit) == 0)
    2575                 :             :                 {
    2576                 :          92 :                         double          cvalue = value * table[i].multiplier;
    2577                 :             : 
    2578                 :             :                         /*
    2579                 :             :                          * If the user gave a fractional value such as "30.1GB", round it
    2580                 :             :                          * off to the nearest multiple of the next smaller unit, if there
    2581                 :             :                          * is one.
    2582                 :             :                          */
    2583   [ +  -  +  + ]:          92 :                         if (*table[i + 1].unit &&
    2584                 :          92 :                                 base_unit == table[i + 1].base_unit)
    2585                 :         182 :                                 cvalue = rint(cvalue / table[i + 1].multiplier) *
    2586                 :          91 :                                         table[i + 1].multiplier;
    2587                 :             : 
    2588                 :          92 :                         *base_value = cvalue;
    2589                 :          92 :                         return true;
    2590                 :          92 :                 }
    2591                 :         792 :         }
    2592                 :           0 :         return false;
    2593                 :          92 : }
    2594                 :             : 
    2595                 :             : /*
    2596                 :             :  * Convert an integer value in some base unit to a human-friendly unit.
    2597                 :             :  *
    2598                 :             :  * The output unit is chosen so that it's the greatest unit that can represent
    2599                 :             :  * the value without loss.  For example, if the base unit is GUC_UNIT_KB, 1024
    2600                 :             :  * is converted to 1 MB, but 1025 is represented as 1025 kB.
    2601                 :             :  */
    2602                 :             : static void
    2603                 :          28 : convert_int_from_base_unit(int64 base_value, int base_unit,
    2604                 :             :                                                    int64 *value, const char **unit)
    2605                 :             : {
    2606                 :          28 :         const unit_conversion *table;
    2607                 :             : 
    2608                 :          28 :         *unit = NULL;
    2609                 :             : 
    2610         [ +  + ]:          28 :         if (base_unit & GUC_UNIT_MEMORY)
    2611                 :          22 :                 table = memory_unit_conversion_table;
    2612                 :             :         else
    2613                 :           6 :                 table = time_unit_conversion_table;
    2614                 :             : 
    2615         [ -  + ]:         271 :         for (int i = 0; *table[i].unit; i++)
    2616                 :             :         {
    2617         [ +  + ]:         243 :                 if (base_unit == table[i].base_unit)
    2618                 :             :                 {
    2619                 :             :                         /*
    2620                 :             :                          * Accept the first conversion that divides the value evenly.  We
    2621                 :             :                          * assume that the conversions for each base unit are ordered from
    2622                 :             :                          * greatest unit to the smallest!
    2623                 :             :                          */
    2624   [ +  +  +  + ]:          83 :                         if (table[i].multiplier <= 1.0 ||
    2625                 :          78 :                                 base_value % (int64) table[i].multiplier == 0)
    2626                 :             :                         {
    2627                 :          28 :                                 *value = (int64) rint(base_value / table[i].multiplier);
    2628                 :          28 :                                 *unit = table[i].unit;
    2629                 :          28 :                                 break;
    2630                 :             :                         }
    2631                 :          55 :                 }
    2632                 :         215 :         }
    2633                 :             : 
    2634         [ +  - ]:          28 :         Assert(*unit != NULL);
    2635                 :          28 : }
    2636                 :             : 
    2637                 :             : /*
    2638                 :             :  * Convert a floating-point value in some base unit to a human-friendly unit.
    2639                 :             :  *
    2640                 :             :  * Same as above, except we have to do the math a bit differently, and
    2641                 :             :  * there's a possibility that we don't find any exact divisor.
    2642                 :             :  */
    2643                 :             : static void
    2644                 :          44 : convert_real_from_base_unit(double base_value, int base_unit,
    2645                 :             :                                                         double *value, const char **unit)
    2646                 :             : {
    2647                 :          44 :         const unit_conversion *table;
    2648                 :             : 
    2649                 :          44 :         *unit = NULL;
    2650                 :             : 
    2651         [ -  + ]:          44 :         if (base_unit & GUC_UNIT_MEMORY)
    2652                 :           0 :                 table = memory_unit_conversion_table;
    2653                 :             :         else
    2654                 :          44 :                 table = time_unit_conversion_table;
    2655                 :             : 
    2656         [ +  - ]:         268 :         for (int i = 0; *table[i].unit; i++)
    2657                 :             :         {
    2658         [ -  + ]:         224 :                 if (base_unit == table[i].base_unit)
    2659                 :             :                 {
    2660                 :             :                         /*
    2661                 :             :                          * Accept the first conversion that divides the value evenly; or
    2662                 :             :                          * if there is none, use the smallest (last) target unit.
    2663                 :             :                          *
    2664                 :             :                          * What we actually care about here is whether snprintf with "%g"
    2665                 :             :                          * will print the value as an integer, so the obvious test of
    2666                 :             :                          * "*value == rint(*value)" is too strict; roundoff error might
    2667                 :             :                          * make us choose an unreasonably small unit.  As a compromise,
    2668                 :             :                          * accept a divisor that is within 1e-8 of producing an integer.
    2669                 :             :                          */
    2670                 :         224 :                         *value = base_value / table[i].multiplier;
    2671                 :         224 :                         *unit = table[i].unit;
    2672   [ +  -  +  + ]:         224 :                         if (*value > 0 &&
    2673                 :         224 :                                 fabs((rint(*value) / *value) - 1.0) <= 1e-8)
    2674                 :          44 :                                 break;
    2675                 :         180 :                 }
    2676                 :         180 :         }
    2677                 :             : 
    2678         [ +  - ]:          44 :         Assert(*unit != NULL);
    2679                 :          44 : }
    2680                 :             : 
    2681                 :             : /*
    2682                 :             :  * Return the name of a GUC's base unit (e.g. "ms") given its flags.
    2683                 :             :  * Return NULL if the GUC is unitless.
    2684                 :             :  */
    2685                 :             : const char *
    2686                 :        2917 : get_config_unit_name(int flags)
    2687                 :             : {
    2688   [ +  +  +  +  :        2917 :         switch (flags & GUC_UNIT)
          +  +  +  +  +  
                      - ]
    2689                 :             :         {
    2690                 :             :                 case 0:
    2691                 :        2363 :                         return NULL;            /* GUC has no units */
    2692                 :             :                 case GUC_UNIT_BYTE:
    2693                 :          35 :                         return "B";
    2694                 :             :                 case GUC_UNIT_KB:
    2695                 :          84 :                         return "kB";
    2696                 :             :                 case GUC_UNIT_MB:
    2697                 :          42 :                         return "MB";
    2698                 :             :                 case GUC_UNIT_BLOCKS:
    2699                 :             :                         {
    2700                 :             :                                 static char bbuf[8];
    2701                 :             : 
    2702                 :             :                                 /* initialize if first time through */
    2703         [ +  + ]:         126 :                                 if (bbuf[0] == '\0')
    2704                 :           5 :                                         snprintf(bbuf, sizeof(bbuf), "%dkB", BLCKSZ / 1024);
    2705                 :         126 :                                 return bbuf;
    2706                 :             :                         }
    2707                 :             :                 case GUC_UNIT_XBLOCKS:
    2708                 :             :                         {
    2709                 :             :                                 static char xbuf[8];
    2710                 :             : 
    2711                 :             :                                 /* initialize if first time through */
    2712         [ +  + ]:          14 :                                 if (xbuf[0] == '\0')
    2713                 :           5 :                                         snprintf(xbuf, sizeof(xbuf), "%dkB", XLOG_BLCKSZ / 1024);
    2714                 :          14 :                                 return xbuf;
    2715                 :             :                         }
    2716                 :             :                 case GUC_UNIT_MS:
    2717                 :         162 :                         return "ms";
    2718                 :             :                 case GUC_UNIT_S:
    2719                 :          77 :                         return "s";
    2720                 :             :                 case GUC_UNIT_MIN:
    2721                 :          14 :                         return "min";
    2722                 :             :                 default:
    2723   [ #  #  #  # ]:           0 :                         elog(ERROR, "unrecognized GUC units value: %d",
    2724                 :             :                                  flags & GUC_UNIT);
    2725                 :           0 :                         return NULL;
    2726                 :             :         }
    2727                 :        2917 : }
    2728                 :             : 
    2729                 :             : 
    2730                 :             : /*
    2731                 :             :  * Try to parse value as an integer.  The accepted formats are the
    2732                 :             :  * usual decimal, octal, or hexadecimal formats, as well as floating-point
    2733                 :             :  * formats (which will be rounded to integer after any units conversion).
    2734                 :             :  * Optionally, the value can be followed by a unit name if "flags" indicates
    2735                 :             :  * a unit is allowed.
    2736                 :             :  *
    2737                 :             :  * If the string parses okay, return true, else false.
    2738                 :             :  * If okay and result is not NULL, return the value in *result.
    2739                 :             :  * If not okay and hintmsg is not NULL, *hintmsg is set to a suitable
    2740                 :             :  * HINT message, or NULL if no hint provided.
    2741                 :             :  */
    2742                 :             : bool
    2743                 :        4955 : parse_int(const char *value, int *result, int flags, const char **hintmsg)
    2744                 :             : {
    2745                 :             :         /*
    2746                 :             :          * We assume here that double is wide enough to represent any integer
    2747                 :             :          * value with adequate precision.
    2748                 :             :          */
    2749                 :        4955 :         double          val;
    2750                 :        4955 :         char       *endptr;
    2751                 :             : 
    2752                 :             :         /* To suppress compiler warnings, always set output params */
    2753         [ -  + ]:        4955 :         if (result)
    2754                 :        4955 :                 *result = 0;
    2755         [ +  + ]:        4955 :         if (hintmsg)
    2756                 :        4005 :                 *hintmsg = NULL;
    2757                 :             : 
    2758                 :             :         /*
    2759                 :             :          * Try to parse as an integer (allowing octal or hex input).  If the
    2760                 :             :          * conversion stops at a decimal point or 'e', or overflows, re-parse as
    2761                 :             :          * float.  This should work fine as long as we have no unit names starting
    2762                 :             :          * with 'e'.  If we ever do, the test could be extended to check for a
    2763                 :             :          * sign or digit after 'e', but for now that's unnecessary.
    2764                 :             :          */
    2765                 :        4955 :         errno = 0;
    2766                 :        4955 :         val = strtol(value, &endptr, 0);
    2767   [ +  +  +  -  :        4955 :         if (*endptr == '.' || *endptr == 'e' || *endptr == 'E' ||
             +  -  -  + ]
    2768                 :        4954 :                 errno == ERANGE)
    2769                 :             :         {
    2770                 :           1 :                 errno = 0;
    2771                 :           1 :                 val = strtod(value, &endptr);
    2772                 :           1 :         }
    2773                 :             : 
    2774   [ +  +  -  + ]:        4955 :         if (endptr == value || errno == ERANGE)
    2775                 :           3 :                 return false;                   /* no HINT for these cases */
    2776                 :             : 
    2777                 :             :         /* reject NaN (infinities will fail range check below) */
    2778   [ -  +  +  +  :        4952 :         if (isnan(val))
                   +  - ]
    2779                 :        9904 :                 return false;                   /* treat same as syntax error; no HINT */
    2780                 :             : 
    2781                 :             :         /* allow whitespace between number and unit */
    2782         [ +  + ]:        4956 :         while (isspace((unsigned char) *endptr))
    2783                 :           4 :                 endptr++;
    2784                 :             : 
    2785                 :             :         /* Handle possible unit */
    2786         [ +  + ]:        4952 :         if (*endptr != '\0')
    2787                 :             :         {
    2788         [ +  - ]:          90 :                 if ((flags & GUC_UNIT) == 0)
    2789                 :           0 :                         return false;           /* this setting does not accept a unit */
    2790                 :             : 
    2791   [ +  -  +  - ]:         180 :                 if (!convert_to_base_unit(val,
    2792                 :          90 :                                                                   endptr, (flags & GUC_UNIT),
    2793                 :             :                                                                   &val))
    2794                 :             :                 {
    2795                 :             :                         /* invalid unit, or garbage after the unit; set hint and fail. */
    2796         [ #  # ]:           0 :                         if (hintmsg)
    2797                 :             :                         {
    2798         [ #  # ]:           0 :                                 if (flags & GUC_UNIT_MEMORY)
    2799                 :           0 :                                         *hintmsg = memory_units_hint;
    2800                 :             :                                 else
    2801                 :           0 :                                         *hintmsg = time_units_hint;
    2802                 :           0 :                         }
    2803                 :           0 :                         return false;
    2804                 :             :                 }
    2805                 :          90 :         }
    2806                 :             : 
    2807                 :             :         /* Round to int, then check for overflow */
    2808                 :        4952 :         val = rint(val);
    2809                 :             : 
    2810   [ +  +  -  + ]:        4952 :         if (val > INT_MAX || val < INT_MIN)
    2811                 :             :         {
    2812         [ -  + ]:           1 :                 if (hintmsg)
    2813                 :           1 :                         *hintmsg = gettext_noop("Value exceeds integer range.");
    2814                 :           1 :                 return false;
    2815                 :             :         }
    2816                 :             : 
    2817         [ -  + ]:        4951 :         if (result)
    2818                 :        4951 :                 *result = (int) val;
    2819                 :        4951 :         return true;
    2820                 :       14859 : }
    2821                 :             : 
    2822                 :             : /*
    2823                 :             :  * Try to parse value as a floating point number in the usual format.
    2824                 :             :  * Optionally, the value can be followed by a unit name if "flags" indicates
    2825                 :             :  * a unit is allowed.
    2826                 :             :  *
    2827                 :             :  * If the string parses okay, return true, else false.
    2828                 :             :  * If okay and result is not NULL, return the value in *result.
    2829                 :             :  * If not okay and hintmsg is not NULL, *hintmsg is set to a suitable
    2830                 :             :  * HINT message, or NULL if no hint provided.
    2831                 :             :  */
    2832                 :             : bool
    2833                 :        1383 : parse_real(const char *value, double *result, int flags, const char **hintmsg)
    2834                 :             : {
    2835                 :        1383 :         double          val;
    2836                 :        1383 :         char       *endptr;
    2837                 :             : 
    2838                 :             :         /* To suppress compiler warnings, always set output params */
    2839         [ -  + ]:        1383 :         if (result)
    2840                 :        1383 :                 *result = 0;
    2841         [ +  + ]:        1383 :         if (hintmsg)
    2842                 :        1324 :                 *hintmsg = NULL;
    2843                 :             : 
    2844                 :        1383 :         errno = 0;
    2845                 :        1383 :         val = strtod(value, &endptr);
    2846                 :             : 
    2847   [ +  +  -  + ]:        1383 :         if (endptr == value || errno == ERANGE)
    2848                 :           2 :                 return false;                   /* no HINT for these cases */
    2849                 :             : 
    2850                 :             :         /* reject NaN (infinities will fail range checks later) */
    2851   [ -  +  +  +  :        1381 :         if (isnan(val))
                   +  - ]
    2852                 :        2761 :                 return false;                   /* treat same as syntax error; no HINT */
    2853                 :             : 
    2854                 :             :         /* allow whitespace between number and unit */
    2855         [ -  + ]:        1380 :         while (isspace((unsigned char) *endptr))
    2856                 :           0 :                 endptr++;
    2857                 :             : 
    2858                 :             :         /* Handle possible unit */
    2859         [ +  + ]:        1380 :         if (*endptr != '\0')
    2860                 :             :         {
    2861         [ +  - ]:           2 :                 if ((flags & GUC_UNIT) == 0)
    2862                 :           0 :                         return false;           /* this setting does not accept a unit */
    2863                 :             : 
    2864   [ +  -  +  - ]:           4 :                 if (!convert_to_base_unit(val,
    2865                 :           2 :                                                                   endptr, (flags & GUC_UNIT),
    2866                 :             :                                                                   &val))
    2867                 :             :                 {
    2868                 :             :                         /* invalid unit, or garbage after the unit; set hint and fail. */
    2869         [ #  # ]:           0 :                         if (hintmsg)
    2870                 :             :                         {
    2871         [ #  # ]:           0 :                                 if (flags & GUC_UNIT_MEMORY)
    2872                 :           0 :                                         *hintmsg = memory_units_hint;
    2873                 :             :                                 else
    2874                 :           0 :                                         *hintmsg = time_units_hint;
    2875                 :           0 :                         }
    2876                 :           0 :                         return false;
    2877                 :             :                 }
    2878                 :           2 :         }
    2879                 :             : 
    2880         [ -  + ]:        1380 :         if (result)
    2881                 :        1380 :                 *result = val;
    2882                 :        1380 :         return true;
    2883                 :        4143 : }
    2884                 :             : 
    2885                 :             : 
    2886                 :             : /*
    2887                 :             :  * Lookup the name for an enum option with the selected value.
    2888                 :             :  * Should only ever be called with known-valid values, so throws
    2889                 :             :  * an elog(ERROR) if the enum option is not found.
    2890                 :             :  *
    2891                 :             :  * The returned string is a pointer to static data and not
    2892                 :             :  * allocated for modification.
    2893                 :             :  */
    2894                 :             : const char *
    2895                 :        2836 : config_enum_lookup_by_value(const struct config_generic *record, int val)
    2896                 :             : {
    2897   [ -  +  +  -  :        9963 :         for (const struct config_enum_entry *entry = record->_enum.options; entry && entry->name; entry++)
                -  +  - ]
    2898                 :             :         {
    2899         [ +  + ]:        7127 :                 if (entry->val == val)
    2900                 :        2836 :                         return entry->name;
    2901                 :        4291 :         }
    2902                 :             : 
    2903   [ #  #  #  # ]:           0 :         elog(ERROR, "could not find enum option %d for %s",
    2904                 :             :                  val, record->name);
    2905                 :           0 :         return NULL;                            /* silence compiler */
    2906                 :        2836 : }
    2907                 :             : 
    2908                 :             : 
    2909                 :             : /*
    2910                 :             :  * Lookup the value for an enum option with the selected name
    2911                 :             :  * (case-insensitive).
    2912                 :             :  * If the enum option is found, sets the retval value and returns
    2913                 :             :  * true. If it's not found, return false and retval is set to 0.
    2914                 :             :  */
    2915                 :             : bool
    2916                 :        3260 : config_enum_lookup_by_name(const struct config_enum *record, const char *value,
    2917                 :             :                                                    int *retval)
    2918                 :             : {
    2919   [ -  +  +  +  :       11950 :         for (const struct config_enum_entry *entry = record->options; entry && entry->name; entry++)
                -  +  + ]
    2920                 :             :         {
    2921         [ +  + ]:        8690 :                 if (pg_strcasecmp(value, entry->name) == 0)
    2922                 :             :                 {
    2923                 :        3254 :                         *retval = entry->val;
    2924                 :        3254 :                         return true;
    2925                 :             :                 }
    2926                 :        5436 :         }
    2927                 :             : 
    2928                 :           6 :         *retval = 0;
    2929                 :           6 :         return false;
    2930                 :        3260 : }
    2931                 :             : 
    2932                 :             : 
    2933                 :             : /*
    2934                 :             :  * Return a palloc'd string listing all the available options for an enum GUC
    2935                 :             :  * (excluding hidden ones), separated by the given separator.
    2936                 :             :  * If prefix is non-NULL, it is added before the first enum value.
    2937                 :             :  * If suffix is non-NULL, it is added to the end of the string.
    2938                 :             :  */
    2939                 :             : char *
    2940                 :         298 : config_enum_get_options(const struct config_enum *record, const char *prefix,
    2941                 :             :                                                 const char *suffix, const char *separator)
    2942                 :             : {
    2943                 :         298 :         StringInfoData retstr;
    2944                 :         298 :         int                     seplen;
    2945                 :             : 
    2946                 :         298 :         initStringInfo(&retstr);
    2947                 :         298 :         appendStringInfoString(&retstr, prefix);
    2948                 :             : 
    2949                 :         298 :         seplen = strlen(separator);
    2950   [ -  +  +  + ]:        1918 :         for (const struct config_enum_entry *entry = record->options; entry && entry->name; entry++)
    2951                 :             :         {
    2952         [ +  + ]:        1620 :                 if (!entry->hidden)
    2953                 :             :                 {
    2954                 :        1166 :                         appendStringInfoString(&retstr, entry->name);
    2955                 :        1166 :                         appendBinaryStringInfo(&retstr, separator, seplen);
    2956                 :        1166 :                 }
    2957                 :        1620 :         }
    2958                 :             : 
    2959                 :             :         /*
    2960                 :             :          * All the entries may have been hidden, leaving the string empty if no
    2961                 :             :          * prefix was given. This indicates a broken GUC setup, since there is no
    2962                 :             :          * use for an enum without any values, so we just check to make sure we
    2963                 :             :          * don't write to invalid memory instead of actually trying to do
    2964                 :             :          * something smart with it.
    2965                 :             :          */
    2966         [ -  + ]:         298 :         if (retstr.len >= seplen)
    2967                 :             :         {
    2968                 :             :                 /* Replace final separator */
    2969                 :         298 :                 retstr.data[retstr.len - seplen] = '\0';
    2970                 :         298 :                 retstr.len -= seplen;
    2971                 :         298 :         }
    2972                 :             : 
    2973                 :         298 :         appendStringInfoString(&retstr, suffix);
    2974                 :             : 
    2975                 :         596 :         return retstr.data;
    2976                 :         298 : }
    2977                 :             : 
    2978                 :             : /*
    2979                 :             :  * Parse and validate a proposed value for the specified configuration
    2980                 :             :  * parameter.
    2981                 :             :  *
    2982                 :             :  * This does built-in checks (such as range limits for an integer parameter)
    2983                 :             :  * and also calls any check hook the parameter may have.
    2984                 :             :  *
    2985                 :             :  * record: GUC variable's info record
    2986                 :             :  * value: proposed value, as a string
    2987                 :             :  * source: identifies source of value (check hooks may need this)
    2988                 :             :  * elevel: level to log any error reports at
    2989                 :             :  * newval: on success, converted parameter value is returned here
    2990                 :             :  * newextra: on success, receives any "extra" data returned by check hook
    2991                 :             :  *      (caller must initialize *newextra to NULL)
    2992                 :             :  *
    2993                 :             :  * Returns true if OK, false if not (or throws error, if elevel >= ERROR)
    2994                 :             :  */
    2995                 :             : static bool
    2996                 :       48487 : parse_and_validate_value(const struct config_generic *record,
    2997                 :             :                                                  const char *value,
    2998                 :             :                                                  GucSource source, int elevel,
    2999                 :             :                                                  union config_var_val *newval, void **newextra)
    3000                 :             : {
    3001   [ -  +  +  +  :       48487 :         switch (record->vartype)
                   +  + ]
    3002                 :             :         {
    3003                 :             :                 case PGC_BOOL:
    3004                 :             :                         {
    3005         [ +  - ]:       10843 :                                 if (!parse_bool(value, &newval->boolval))
    3006                 :             :                                 {
    3007   [ #  #  #  #  :           0 :                                         ereport(elevel,
          #  #  #  #  #  
                      # ]
    3008                 :             :                                                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    3009                 :             :                                                          errmsg("parameter \"%s\" requires a Boolean value",
    3010                 :             :                                                                         record->name)));
    3011                 :           0 :                                         return false;
    3012                 :             :                                 }
    3013                 :             : 
    3014   [ +  -  +  - ]:       21686 :                                 if (!call_bool_check_hook(record, &newval->boolval, newextra,
    3015                 :       10843 :                                                                                   source, elevel))
    3016                 :           0 :                                         return false;
    3017                 :             :                         }
    3018                 :       10843 :                         break;
    3019                 :             :                 case PGC_INT:
    3020                 :             :                         {
    3021                 :        3996 :                                 const struct config_int *conf = &record->_int;
    3022                 :        3996 :                                 const char *hintmsg;
    3023                 :             : 
    3024   [ +  -  +  - ]:        7992 :                                 if (!parse_int(value, &newval->intval,
    3025                 :        3996 :                                                            record->flags, &hintmsg))
    3026                 :             :                                 {
    3027   [ #  #  #  #  :           0 :                                         ereport(elevel,
          #  #  #  #  #  
                #  #  # ]
    3028                 :             :                                                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    3029                 :             :                                                          errmsg("invalid value for parameter \"%s\": \"%s\"",
    3030                 :             :                                                                         record->name, value),
    3031                 :             :                                                          hintmsg ? errhint("%s", _(hintmsg)) : 0));
    3032                 :           0 :                                         return false;
    3033                 :             :                                 }
    3034                 :             : 
    3035   [ +  -  -  + ]:        3996 :                                 if (newval->intval < conf->min || newval->intval > conf->max)
    3036                 :             :                                 {
    3037                 :           0 :                                         const char *unit = get_config_unit_name(record->flags);
    3038                 :           0 :                                         const char *unitspace;
    3039                 :             : 
    3040         [ #  # ]:           0 :                                         if (unit)
    3041                 :           0 :                                                 unitspace = " ";
    3042                 :             :                                         else
    3043                 :           0 :                                                 unit = unitspace = "";
    3044                 :             : 
    3045   [ #  #  #  #  :           0 :                                         ereport(elevel,
          #  #  #  #  #  
                      # ]
    3046                 :             :                                                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    3047                 :             :                                                          errmsg("%d%s%s is outside the valid range for parameter \"%s\" (%d%s%s .. %d%s%s)",
    3048                 :             :                                                                         newval->intval, unitspace, unit,
    3049                 :             :                                                                         record->name,
    3050                 :             :                                                                         conf->min, unitspace, unit,
    3051                 :             :                                                                         conf->max, unitspace, unit)));
    3052                 :           0 :                                         return false;
    3053                 :           0 :                                 }
    3054                 :             : 
    3055   [ +  -  +  - ]:        7992 :                                 if (!call_int_check_hook(record, &newval->intval, newextra,
    3056                 :        3996 :                                                                                  source, elevel))
    3057                 :           0 :                                         return false;
    3058         [ -  + ]:        3996 :                         }
    3059                 :        3996 :                         break;
    3060                 :             :                 case PGC_REAL:
    3061                 :             :                         {
    3062                 :        1325 :                                 const struct config_real *conf = &record->_real;
    3063                 :        1325 :                                 const char *hintmsg;
    3064                 :             : 
    3065   [ +  +  +  + ]:        2650 :                                 if (!parse_real(value, &newval->realval,
    3066                 :        1325 :                                                                 record->flags, &hintmsg))
    3067                 :             :                                 {
    3068   [ -  +  #  #  :           2 :                                         ereport(elevel,
          +  +  -  +  #  
                #  #  # ]
    3069                 :             :                                                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    3070                 :             :                                                          errmsg("invalid value for parameter \"%s\": \"%s\"",
    3071                 :             :                                                                         record->name, value),
    3072                 :             :                                                          hintmsg ? errhint("%s", _(hintmsg)) : 0));
    3073                 :           0 :                                         return false;
    3074                 :             :                                 }
    3075                 :             : 
    3076   [ +  -  +  + ]:        1323 :                                 if (newval->realval < conf->min || newval->realval > conf->max)
    3077                 :             :                                 {
    3078                 :           1 :                                         const char *unit = get_config_unit_name(record->flags);
    3079                 :           1 :                                         const char *unitspace;
    3080                 :             : 
    3081         [ +  - ]:           1 :                                         if (unit)
    3082                 :           1 :                                                 unitspace = " ";
    3083                 :             :                                         else
    3084                 :           0 :                                                 unit = unitspace = "";
    3085                 :             : 
    3086   [ -  +  #  #  :           1 :                                         ereport(elevel,
          +  -  -  +  #  
                      # ]
    3087                 :             :                                                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    3088                 :             :                                                          errmsg("%g%s%s is outside the valid range for parameter \"%s\" (%g%s%s .. %g%s%s)",
    3089                 :             :                                                                         newval->realval, unitspace, unit,
    3090                 :             :                                                                         record->name,
    3091                 :             :                                                                         conf->min, unitspace, unit,
    3092                 :             :                                                                         conf->max, unitspace, unit)));
    3093                 :           1 :                                         return false;
    3094                 :           1 :                                 }
    3095                 :             : 
    3096   [ +  -  +  - ]:        2644 :                                 if (!call_real_check_hook(record, &newval->realval, newextra,
    3097                 :        1322 :                                                                                   source, elevel))
    3098                 :           0 :                                         return false;
    3099         [ +  + ]:        1323 :                         }
    3100                 :        1322 :                         break;
    3101                 :             :                 case PGC_STRING:
    3102                 :             :                         {
    3103                 :             :                                 /*
    3104                 :             :                                  * The value passed by the caller could be transient, so we
    3105                 :             :                                  * always strdup it.
    3106                 :             :                                  */
    3107                 :       29057 :                                 newval->stringval = guc_strdup(elevel, value);
    3108         [ -  + ]:       29057 :                                 if (newval->stringval == NULL)
    3109                 :           0 :                                         return false;
    3110                 :             : 
    3111                 :             :                                 /*
    3112                 :             :                                  * The only built-in "parsing" check we have is to apply
    3113                 :             :                                  * truncation if GUC_IS_NAME.
    3114                 :             :                                  */
    3115         [ +  + ]:       29057 :                                 if (record->flags & GUC_IS_NAME)
    3116                 :       11080 :                                         truncate_identifier(newval->stringval,
    3117                 :        5540 :                                                                                 strlen(newval->stringval),
    3118                 :             :                                                                                 true);
    3119                 :             : 
    3120   [ +  -  +  - ]:       58114 :                                 if (!call_string_check_hook(record, &newval->stringval, newextra,
    3121                 :       29057 :                                                                                         source, elevel))
    3122                 :             :                                 {
    3123                 :           0 :                                         guc_free(newval->stringval);
    3124                 :           0 :                                         newval->stringval = NULL;
    3125                 :           0 :                                         return false;
    3126                 :             :                                 }
    3127                 :             :                         }
    3128                 :       29057 :                         break;
    3129                 :             :                 case PGC_ENUM:
    3130                 :             :                         {
    3131                 :        3266 :                                 const struct config_enum *conf = &record->_enum;
    3132                 :             : 
    3133         [ +  + ]:        3266 :                                 if (!config_enum_lookup_by_name(conf, value, &newval->enumval))
    3134                 :             :                                 {
    3135                 :          12 :                                         char       *hintmsg;
    3136                 :             : 
    3137                 :          24 :                                         hintmsg = config_enum_get_options(conf,
    3138                 :          12 :                                                                                                           _("Available values: "),
    3139                 :             : 
    3140                 :             :                                         /*
    3141                 :             :                                          * translator: This is the terminator of a list of entity
    3142                 :             :                                          * names.
    3143                 :             :                                          */
    3144                 :          12 :                                                                                                           _("."),
    3145                 :             : 
    3146                 :             :                                         /*
    3147                 :             :                                          * translator: This is a separator in a list of entity
    3148                 :             :                                          * names.
    3149                 :             :                                          */
    3150                 :          12 :                                                                                                           _(", "));
    3151                 :             : 
    3152   [ -  +  #  #  :          12 :                                         ereport(elevel,
          +  +  +  -  #  
                #  #  # ]
    3153                 :             :                                                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    3154                 :             :                                                          errmsg("invalid value for parameter \"%s\": \"%s\"",
    3155                 :             :                                                                         record->name, value),
    3156                 :             :                                                          hintmsg ? errhint("%s", hintmsg) : 0));
    3157                 :             : 
    3158         [ #  # ]:           0 :                                         if (hintmsg)
    3159                 :           0 :                                                 pfree(hintmsg);
    3160                 :           0 :                                         return false;
    3161                 :           0 :                                 }
    3162                 :             : 
    3163   [ +  -  +  - ]:        6508 :                                 if (!call_enum_check_hook(record, &newval->enumval, newextra,
    3164                 :        3254 :                                                                                   source, elevel))
    3165                 :           0 :                                         return false;
    3166         [ -  + ]:        3254 :                         }
    3167                 :        3254 :                         break;
    3168                 :             :         }
    3169                 :             : 
    3170                 :       48472 :         return true;
    3171                 :       48473 : }
    3172                 :             : 
    3173                 :             : 
    3174                 :             : /*
    3175                 :             :  * set_config_option: sets option `name' to given value.
    3176                 :             :  *
    3177                 :             :  * The value should be a string, which will be parsed and converted to
    3178                 :             :  * the appropriate data type.  The context and source parameters indicate
    3179                 :             :  * in which context this function is being called, so that it can apply the
    3180                 :             :  * access restrictions properly.
    3181                 :             :  *
    3182                 :             :  * If value is NULL, set the option to its default value (normally the
    3183                 :             :  * reset_val, but if source == PGC_S_DEFAULT we instead use the boot_val).
    3184                 :             :  *
    3185                 :             :  * action indicates whether to set the value globally in the session, locally
    3186                 :             :  * to the current top transaction, or just for the duration of a function call.
    3187                 :             :  *
    3188                 :             :  * If changeVal is false then don't really set the option but do all
    3189                 :             :  * the checks to see if it would work.
    3190                 :             :  *
    3191                 :             :  * elevel should normally be passed as zero, allowing this function to make
    3192                 :             :  * its standard choice of ereport level.  However some callers need to be
    3193                 :             :  * able to override that choice; they should pass the ereport level to use.
    3194                 :             :  *
    3195                 :             :  * is_reload should be true only when called from read_nondefault_variables()
    3196                 :             :  * or RestoreGUCState(), where we are trying to load some other process's
    3197                 :             :  * GUC settings into a new process.
    3198                 :             :  *
    3199                 :             :  * Return value:
    3200                 :             :  *      +1: the value is valid and was successfully applied.
    3201                 :             :  *      0:      the name or value is invalid, or it's invalid to try to set
    3202                 :             :  *              this GUC now; but elevel was less than ERROR (see below).
    3203                 :             :  *      -1: no error detected, but the value was not applied, either
    3204                 :             :  *              because changeVal is false or there is some overriding setting.
    3205                 :             :  *
    3206                 :             :  * If there is an error (non-existing option, invalid value, etc) then an
    3207                 :             :  * ereport(ERROR) is thrown *unless* this is called for a source for which
    3208                 :             :  * we don't want an ERROR (currently, those are defaults, the config file,
    3209                 :             :  * and per-database or per-user settings, as well as callers who specify
    3210                 :             :  * a less-than-ERROR elevel).  In those cases we write a suitable error
    3211                 :             :  * message via ereport() and return 0.
    3212                 :             :  *
    3213                 :             :  * See also SetConfigOption for an external interface.
    3214                 :             :  */
    3215                 :             : int
    3216                 :       30156 : set_config_option(const char *name, const char *value,
    3217                 :             :                                   GucContext context, GucSource source,
    3218                 :             :                                   GucAction action, bool changeVal, int elevel,
    3219                 :             :                                   bool is_reload)
    3220                 :             : {
    3221                 :       30156 :         Oid                     srole;
    3222                 :             : 
    3223                 :             :         /*
    3224                 :             :          * Non-interactive sources should be treated as having all privileges,
    3225                 :             :          * except for PGC_S_CLIENT.  Note in particular that this is true for
    3226                 :             :          * pg_db_role_setting sources (PGC_S_GLOBAL etc): we assume a suitable
    3227                 :             :          * privilege check was done when the pg_db_role_setting entry was made.
    3228                 :             :          */
    3229   [ +  +  +  + ]:       30156 :         if (source >= PGC_S_INTERACTIVE || source == PGC_S_CLIENT)
    3230                 :       19439 :                 srole = GetUserId();
    3231                 :             :         else
    3232                 :       10717 :                 srole = BOOTSTRAP_SUPERUSERID;
    3233                 :             : 
    3234                 :       90468 :         return set_config_with_handle(name, NULL, value,
    3235                 :       30156 :                                                                   context, source, srole,
    3236                 :       30156 :                                                                   action, changeVal, elevel,
    3237                 :       30156 :                                                                   is_reload);
    3238                 :       30156 : }
    3239                 :             : 
    3240                 :             : /*
    3241                 :             :  * set_config_option_ext: sets option `name' to given value.
    3242                 :             :  *
    3243                 :             :  * This API adds the ability to explicitly specify which role OID
    3244                 :             :  * is considered to be setting the value.  Most external callers can use
    3245                 :             :  * set_config_option() and let it determine that based on the GucSource,
    3246                 :             :  * but there are a few that are supplying a value that was determined
    3247                 :             :  * in some special way and need to override the decision.  Also, when
    3248                 :             :  * restoring a previously-assigned value, it's important to supply the
    3249                 :             :  * same role OID that set the value originally; so all guc.c callers
    3250                 :             :  * that are doing that type of thing need to call this directly.
    3251                 :             :  *
    3252                 :             :  * Generally, srole should be GetUserId() when the source is a SQL operation,
    3253                 :             :  * or BOOTSTRAP_SUPERUSERID if the source is a config file or similar.
    3254                 :             :  */
    3255                 :             : int
    3256                 :       18310 : set_config_option_ext(const char *name, const char *value,
    3257                 :             :                                           GucContext context, GucSource source, Oid srole,
    3258                 :             :                                           GucAction action, bool changeVal, int elevel,
    3259                 :             :                                           bool is_reload)
    3260                 :             : {
    3261                 :       36620 :         return set_config_with_handle(name, NULL, value,
    3262                 :       18310 :                                                                   context, source, srole,
    3263                 :       18310 :                                                                   action, changeVal, elevel,
    3264                 :       18310 :                                                                   is_reload);
    3265                 :             : }
    3266                 :             : 
    3267                 :             : 
    3268                 :             : /*
    3269                 :             :  * set_config_with_handle: sets option `name' to given value.
    3270                 :             :  *
    3271                 :             :  * This API adds the ability to pass a 'handle' argument, which can be
    3272                 :             :  * obtained by the caller from get_config_handle().  NULL has no effect,
    3273                 :             :  * but a non-null value avoids the need to search the GUC tables.
    3274                 :             :  *
    3275                 :             :  * This should be used by callers which repeatedly set the same config
    3276                 :             :  * option(s), and want to avoid the overhead of a hash lookup each time.
    3277                 :             :  */
    3278                 :             : int
    3279                 :       49362 : set_config_with_handle(const char *name, config_handle *handle,
    3280                 :             :                                            const char *value,
    3281                 :             :                                            GucContext context, GucSource source, Oid srole,
    3282                 :             :                                            GucAction action, bool changeVal, int elevel,
    3283                 :             :                                            bool is_reload)
    3284                 :             : {
    3285                 :       49362 :         struct config_generic *record;
    3286                 :       49362 :         union config_var_val newval_union;
    3287                 :       49362 :         void       *newextra = NULL;
    3288                 :       49362 :         bool            prohibitValueChange = false;
    3289                 :       49362 :         bool            makeDefault;
    3290                 :             : 
    3291         [ +  + ]:       49362 :         if (elevel == 0)
    3292                 :             :         {
    3293   [ +  -  +  + ]:       30176 :                 if (source == PGC_S_DEFAULT || source == PGC_S_FILE)
    3294                 :             :                 {
    3295                 :             :                         /*
    3296                 :             :                          * To avoid cluttering the log, only the postmaster bleats loudly
    3297                 :             :                          * about problems with the config file.
    3298                 :             :                          */
    3299                 :         109 :                         elevel = IsUnderPostmaster ? DEBUG3 : LOG;
    3300                 :         109 :                 }
    3301         [ +  - ]:       30067 :                 else if (source == PGC_S_GLOBAL ||
    3302         [ +  + ]:       30067 :                                  source == PGC_S_DATABASE ||
    3303   [ +  -  -  + ]:       25465 :                                  source == PGC_S_USER ||
    3304                 :       25465 :                                  source == PGC_S_DATABASE_USER)
    3305                 :        4602 :                         elevel = WARNING;
    3306                 :             :                 else
    3307                 :       25465 :                         elevel = ERROR;
    3308                 :       30176 :         }
    3309                 :             : 
    3310                 :             :         /* if handle is specified, no need to look up option */
    3311         [ +  + ]:       49362 :         if (!handle)
    3312                 :             :         {
    3313                 :       49342 :                 record = find_option(name, true, false, elevel);
    3314         [ +  - ]:       49342 :                 if (record == NULL)
    3315                 :           0 :                         return 0;
    3316                 :       49342 :         }
    3317                 :             :         else
    3318                 :          20 :                 record = handle;
    3319                 :             : 
    3320                 :             :         /*
    3321                 :             :          * GUC_ACTION_SAVE changes are acceptable during a parallel operation,
    3322                 :             :          * because the current worker will also pop the change.  We're probably
    3323                 :             :          * dealing with a function having a proconfig entry.  Only the function's
    3324                 :             :          * body should observe the change, and peer workers do not share in the
    3325                 :             :          * execution of a function call started by this worker.
    3326                 :             :          *
    3327                 :             :          * Also allow normal setting if the GUC is marked GUC_ALLOW_IN_PARALLEL.
    3328                 :             :          *
    3329                 :             :          * Other changes might need to affect other workers, so forbid them.
    3330                 :             :          */
    3331   [ +  +  +  -  :       49362 :         if (IsInParallelMode() && changeVal && action != GUC_ACTION_SAVE &&
             +  +  +  - ]
    3332                 :           3 :                 (record->flags & GUC_ALLOW_IN_PARALLEL) == 0)
    3333                 :             :         {
    3334   [ #  #  #  #  :           0 :                 ereport(elevel,
          #  #  #  #  #  
                      # ]
    3335                 :             :                                 (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
    3336                 :             :                                  errmsg("parameter \"%s\" cannot be set during a parallel operation",
    3337                 :             :                                                 record->name)));
    3338                 :           0 :                 return 0;
    3339                 :             :         }
    3340                 :             : 
    3341                 :             :         /*
    3342                 :             :          * Check if the option can be set at this time. See guc.h for the precise
    3343                 :             :          * rules.
    3344                 :             :          */
    3345   [ +  -  +  +  :       49362 :         switch (record->context)
                +  -  + ]
    3346                 :             :         {
    3347                 :             :                 case PGC_INTERNAL:
    3348         [ -  + ]:        4766 :                         if (context != PGC_INTERNAL)
    3349                 :             :                         {
    3350   [ #  #  #  #  :           0 :                                 ereport(elevel,
          #  #  #  #  #  
                      # ]
    3351                 :             :                                                 (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
    3352                 :             :                                                  errmsg("parameter \"%s\" cannot be changed",
    3353                 :             :                                                                 record->name)));
    3354                 :           0 :                                 return 0;
    3355                 :             :                         }
    3356                 :        4766 :                         break;
    3357                 :             :                 case PGC_POSTMASTER:
    3358         [ +  + ]:         100 :                         if (context == PGC_SIGHUP)
    3359                 :             :                         {
    3360                 :             :                                 /*
    3361                 :             :                                  * We are re-reading a PGC_POSTMASTER variable from
    3362                 :             :                                  * postgresql.conf.  We can't change the setting, so we should
    3363                 :             :                                  * give a warning if the DBA tries to change it.  However,
    3364                 :             :                                  * because of variant formats, canonicalization by check
    3365                 :             :                                  * hooks, etc, we can't just compare the given string directly
    3366                 :             :                                  * to what's stored.  Set a flag to check below after we have
    3367                 :             :                                  * the final storable value.
    3368                 :             :                                  */
    3369                 :          10 :                                 prohibitValueChange = true;
    3370                 :          10 :                         }
    3371         [ -  + ]:          90 :                         else if (context != PGC_POSTMASTER)
    3372                 :             :                         {
    3373   [ #  #  #  #  :           0 :                                 ereport(elevel,
          #  #  #  #  #  
                      # ]
    3374                 :             :                                                 (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
    3375                 :             :                                                  errmsg("parameter \"%s\" cannot be changed without restarting the server",
    3376                 :             :                                                                 record->name)));
    3377                 :           0 :                                 return 0;
    3378                 :             :                         }
    3379                 :         100 :                         break;
    3380                 :             :                 case PGC_SIGHUP:
    3381   [ +  +  +  - ]:        3378 :                         if (context != PGC_SIGHUP && context != PGC_POSTMASTER)
    3382                 :             :                         {
    3383   [ #  #  #  #  :           0 :                                 ereport(elevel,
          #  #  #  #  #  
                      # ]
    3384                 :             :                                                 (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
    3385                 :             :                                                  errmsg("parameter \"%s\" cannot be changed now",
    3386                 :             :                                                                 record->name)));
    3387                 :           0 :                                 return 0;
    3388                 :             :                         }
    3389                 :             : 
    3390                 :             :                         /*
    3391                 :             :                          * Hmm, the idea of the SIGHUP context is "ought to be global, but
    3392                 :             :                          * can be changed after postmaster start". But there's nothing
    3393                 :             :                          * that prevents a crafty administrator from sending SIGHUP
    3394                 :             :                          * signals to individual backends only.
    3395                 :             :                          */
    3396                 :        3378 :                         break;
    3397                 :             :                 case PGC_SU_BACKEND:
    3398         [ #  # ]:           0 :                         if (context == PGC_BACKEND)
    3399                 :             :                         {
    3400                 :             :                                 /*
    3401                 :             :                                  * Check whether the requesting user has been granted
    3402                 :             :                                  * privilege to set this GUC.
    3403                 :             :                                  */
    3404                 :           0 :                                 AclResult       aclresult;
    3405                 :             : 
    3406                 :           0 :                                 aclresult = pg_parameter_aclcheck(record->name, srole, ACL_SET);
    3407         [ #  # ]:           0 :                                 if (aclresult != ACLCHECK_OK)
    3408                 :             :                                 {
    3409                 :             :                                         /* No granted privilege */
    3410   [ #  #  #  #  :           0 :                                         ereport(elevel,
          #  #  #  #  #  
                      # ]
    3411                 :             :                                                         (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
    3412                 :             :                                                          errmsg("permission denied to set parameter \"%s\"",
    3413                 :             :                                                                         record->name)));
    3414                 :           0 :                                         return 0;
    3415                 :             :                                 }
    3416         [ #  # ]:           0 :                         }
    3417                 :             :                         /* fall through to process the same as PGC_BACKEND */
    3418                 :             :                         /* FALLTHROUGH */
    3419                 :             :                 case PGC_BACKEND:
    3420         [ #  # ]:           0 :                         if (context == PGC_SIGHUP)
    3421                 :             :                         {
    3422                 :             :                                 /*
    3423                 :             :                                  * If a PGC_BACKEND or PGC_SU_BACKEND parameter is changed in
    3424                 :             :                                  * the config file, we want to accept the new value in the
    3425                 :             :                                  * postmaster (whence it will propagate to
    3426                 :             :                                  * subsequently-started backends), but ignore it in existing
    3427                 :             :                                  * backends.  This is a tad klugy, but necessary because we
    3428                 :             :                                  * don't re-read the config file during backend start.
    3429                 :             :                                  *
    3430                 :             :                                  * However, if changeVal is false then plow ahead anyway since
    3431                 :             :                                  * we are trying to find out if the value is potentially good,
    3432                 :             :                                  * not actually use it.
    3433                 :             :                                  *
    3434                 :             :                                  * In EXEC_BACKEND builds, this works differently: we load all
    3435                 :             :                                  * non-default settings from the CONFIG_EXEC_PARAMS file
    3436                 :             :                                  * during backend start.  In that case we must accept
    3437                 :             :                                  * PGC_SIGHUP settings, so as to have the same value as if
    3438                 :             :                                  * we'd forked from the postmaster.  This can also happen when
    3439                 :             :                                  * using RestoreGUCState() within a background worker that
    3440                 :             :                                  * needs to have the same settings as the user backend that
    3441                 :             :                                  * started it. is_reload will be true when either situation
    3442                 :             :                                  * applies.
    3443                 :             :                                  */
    3444   [ #  #  #  #  :           0 :                                 if (IsUnderPostmaster && changeVal && !is_reload)
                   #  # ]
    3445                 :           0 :                                         return -1;
    3446                 :           0 :                         }
    3447         [ #  # ]:           0 :                         else if (context != PGC_POSTMASTER &&
    3448         [ #  # ]:           0 :                                          context != PGC_BACKEND &&
    3449   [ #  #  #  # ]:           0 :                                          context != PGC_SU_BACKEND &&
    3450                 :           0 :                                          source != PGC_S_CLIENT)
    3451                 :             :                         {
    3452   [ #  #  #  #  :           0 :                                 ereport(elevel,
          #  #  #  #  #  
                      # ]
    3453                 :             :                                                 (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
    3454                 :             :                                                  errmsg("parameter \"%s\" cannot be set after connection start",
    3455                 :             :                                                                 record->name)));
    3456                 :           0 :                                 return 0;
    3457                 :             :                         }
    3458                 :           0 :                         break;
    3459                 :             :                 case PGC_SUSET:
    3460   [ +  -  -  + ]:        3684 :                         if (context == PGC_USERSET || context == PGC_BACKEND)
    3461                 :             :                         {
    3462                 :             :                                 /*
    3463                 :             :                                  * Check whether the requesting user has been granted
    3464                 :             :                                  * privilege to set this GUC.
    3465                 :             :                                  */
    3466                 :           0 :                                 AclResult       aclresult;
    3467                 :             : 
    3468                 :           0 :                                 aclresult = pg_parameter_aclcheck(record->name, srole, ACL_SET);
    3469         [ #  # ]:           0 :                                 if (aclresult != ACLCHECK_OK)
    3470                 :             :                                 {
    3471                 :             :                                         /* No granted privilege */
    3472   [ #  #  #  #  :           0 :                                         ereport(elevel,
          #  #  #  #  #  
                      # ]
    3473                 :             :                                                         (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
    3474                 :             :                                                          errmsg("permission denied to set parameter \"%s\"",
    3475                 :             :                                                                         record->name)));
    3476                 :           0 :                                         return 0;
    3477                 :             :                                 }
    3478         [ #  # ]:           0 :                         }
    3479                 :        3684 :                         break;
    3480                 :             :                 case PGC_USERSET:
    3481                 :             :                         /* always okay */
    3482                 :             :                         break;
    3483                 :             :         }
    3484                 :             : 
    3485                 :             :         /*
    3486                 :             :          * Disallow changing GUC_NOT_WHILE_SEC_REST values if we are inside a
    3487                 :             :          * security restriction context.  We can reject this regardless of the GUC
    3488                 :             :          * context or source, mainly because sources that it might be reasonable
    3489                 :             :          * to override for won't be seen while inside a function.
    3490                 :             :          *
    3491                 :             :          * Note: variables marked GUC_NOT_WHILE_SEC_REST should usually be marked
    3492                 :             :          * GUC_NO_RESET_ALL as well, because ResetAllOptions() doesn't check this.
    3493                 :             :          * An exception might be made if the reset value is assumed to be "safe".
    3494                 :             :          *
    3495                 :             :          * Note: this flag is currently used for "session_authorization" and
    3496                 :             :          * "role".  We need to prohibit changing these inside a local userid
    3497                 :             :          * context because when we exit it, GUC won't be notified, leaving things
    3498                 :             :          * out of sync.  (This could be fixed by forcing a new GUC nesting level,
    3499                 :             :          * but that would change behavior in possibly-undesirable ways.)  Also, we
    3500                 :             :          * prohibit changing these in a security-restricted operation because
    3501                 :             :          * otherwise RESET could be used to regain the session user's privileges.
    3502                 :             :          */
    3503         [ +  + ]:       49362 :         if (record->flags & GUC_NOT_WHILE_SEC_REST)
    3504                 :             :         {
    3505         [ -  + ]:        2947 :                 if (InLocalUserIdChange())
    3506                 :             :                 {
    3507                 :             :                         /*
    3508                 :             :                          * Phrasing of this error message is historical, but it's the most
    3509                 :             :                          * common case.
    3510                 :             :                          */
    3511   [ #  #  #  #  :           0 :                         ereport(elevel,
          #  #  #  #  #  
                      # ]
    3512                 :             :                                         (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
    3513                 :             :                                          errmsg("cannot set parameter \"%s\" within security-definer function",
    3514                 :             :                                                         record->name)));
    3515                 :           0 :                         return 0;
    3516                 :             :                 }
    3517         [ -  + ]:        2947 :                 if (InSecurityRestrictedOperation())
    3518                 :             :                 {
    3519   [ #  #  #  #  :           0 :                         ereport(elevel,
          #  #  #  #  #  
                      # ]
    3520                 :             :                                         (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
    3521                 :             :                                          errmsg("cannot set parameter \"%s\" within security-restricted operation",
    3522                 :             :                                                         record->name)));
    3523                 :           0 :                         return 0;
    3524                 :             :                 }
    3525                 :        2947 :         }
    3526                 :             : 
    3527                 :             :         /* Disallow resetting and saving GUC_NO_RESET values */
    3528         [ +  + ]:       49362 :         if (record->flags & GUC_NO_RESET)
    3529                 :             :         {
    3530         [ +  + ]:        1533 :                 if (value == NULL)
    3531                 :             :                 {
    3532   [ -  +  #  #  :           6 :                         ereport(elevel,
          +  +  #  #  #  
                      # ]
    3533                 :             :                                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    3534                 :             :                                          errmsg("parameter \"%s\" cannot be reset", record->name)));
    3535                 :           0 :                         return 0;
    3536                 :             :                 }
    3537         [ +  + ]:        1527 :                 if (action == GUC_ACTION_SAVE)
    3538                 :             :                 {
    3539   [ -  +  #  #  :           2 :                         ereport(elevel,
          +  +  #  #  #  
                      # ]
    3540                 :             :                                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    3541                 :             :                                          errmsg("parameter \"%s\" cannot be set locally in functions",
    3542                 :             :                                                         record->name)));
    3543                 :           0 :                         return 0;
    3544                 :             :                 }
    3545                 :        1525 :         }
    3546                 :             : 
    3547                 :             :         /*
    3548                 :             :          * Should we set reset/stacked values?  (If so, the behavior is not
    3549                 :             :          * transactional.)      This is done either when we get a default value from
    3550                 :             :          * the database's/user's/client's default settings or when we reset a
    3551                 :             :          * value to its default.
    3552                 :             :          */
    3553   [ +  +  +  + ]:       76321 :         makeDefault = changeVal && (source <= PGC_S_OVERRIDE) &&
    3554         [ +  - ]:       26967 :                 ((value != NULL) || source == PGC_S_DEFAULT);
    3555                 :             : 
    3556                 :             :         /*
    3557                 :             :          * Ignore attempted set if overridden by previously processed setting.
    3558                 :             :          * However, if changeVal is false then plow ahead anyway since we are
    3559                 :             :          * trying to find out if the value is potentially good, not actually use
    3560                 :             :          * it. Also keep going if makeDefault is true, since we may want to set
    3561                 :             :          * the reset/stacked values even if we can't set the variable itself.
    3562                 :             :          */
    3563         [ +  + ]:       49354 :         if (record->source > source)
    3564                 :             :         {
    3565   [ -  +  #  # ]:          12 :                 if (changeVal && !makeDefault)
    3566                 :             :                 {
    3567   [ #  #  #  # ]:           0 :                         elog(DEBUG3, "\"%s\": setting ignored because previous source is higher priority",
    3568                 :             :                                  record->name);
    3569                 :           0 :                         return -1;
    3570                 :             :                 }
    3571                 :          12 :                 changeVal = false;
    3572                 :          12 :         }
    3573                 :             : 
    3574                 :             :         /*
    3575                 :             :          * Evaluate value and set variable.
    3576                 :             :          */
    3577   [ +  +  +  +  :       49354 :         switch (record->vartype)
                   +  + ]
    3578                 :             :         {
    3579                 :             :                 case PGC_BOOL:
    3580                 :             :                         {
    3581                 :       11084 :                                 struct config_bool *conf = &record->_bool;
    3582                 :             : 
    3583                 :             : #define newval (newval_union.boolval)
    3584                 :             : 
    3585         [ +  + ]:       11084 :                                 if (value)
    3586                 :             :                                 {
    3587   [ +  -  +  - ]:       21686 :                                         if (!parse_and_validate_value(record, value,
    3588                 :       10843 :                                                                                                   source, elevel,
    3589                 :             :                                                                                                   &newval_union, &newextra))
    3590                 :           0 :                                                 return 0;
    3591                 :       10843 :                                 }
    3592         [ +  - ]:         241 :                                 else if (source == PGC_S_DEFAULT)
    3593                 :             :                                 {
    3594                 :           0 :                                         newval = conf->boot_val;
    3595   [ #  #  #  # ]:           0 :                                         if (!call_bool_check_hook(record, &newval, &newextra,
    3596                 :           0 :                                                                                           source, elevel))
    3597                 :           0 :                                                 return 0;
    3598                 :           0 :                                 }
    3599                 :             :                                 else
    3600                 :             :                                 {
    3601                 :         241 :                                         newval = conf->reset_val;
    3602                 :         241 :                                         newextra = record->reset_extra;
    3603                 :         241 :                                         source = record->reset_source;
    3604                 :         241 :                                         context = record->reset_scontext;
    3605                 :         241 :                                         srole = record->reset_srole;
    3606                 :             :                                 }
    3607                 :             : 
    3608         [ -  + ]:       11084 :                                 if (prohibitValueChange)
    3609                 :             :                                 {
    3610                 :             :                                         /* Release newextra, unless it's reset_extra */
    3611   [ #  #  #  # ]:           0 :                                         if (newextra && !extra_field_used(record, newextra))
    3612                 :           0 :                                                 guc_free(newextra);
    3613                 :             : 
    3614         [ #  # ]:           0 :                                         if (*conf->variable != newval)
    3615                 :             :                                         {
    3616                 :           0 :                                                 record->status |= GUC_PENDING_RESTART;
    3617   [ #  #  #  #  :           0 :                                                 ereport(elevel,
          #  #  #  #  #  
                      # ]
    3618                 :             :                                                                 (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
    3619                 :             :                                                                  errmsg("parameter \"%s\" cannot be changed without restarting the server",
    3620                 :             :                                                                                 record->name)));
    3621                 :           0 :                                                 return 0;
    3622                 :             :                                         }
    3623                 :           0 :                                         record->status &= ~GUC_PENDING_RESTART;
    3624                 :           0 :                                         return -1;
    3625                 :             :                                 }
    3626                 :             : 
    3627         [ +  + ]:       11084 :                                 if (changeVal)
    3628                 :             :                                 {
    3629                 :             :                                         /* Save old value to support transaction abort */
    3630         [ +  + ]:       11078 :                                         if (!makeDefault)
    3631                 :        3759 :                                                 push_old_value(record, action);
    3632                 :             : 
    3633         [ +  - ]:       11078 :                                         if (conf->assign_hook)
    3634                 :           0 :                                                 conf->assign_hook(newval, newextra);
    3635                 :       11078 :                                         *conf->variable = newval;
    3636                 :       22156 :                                         set_extra_field(record, &record->extra,
    3637                 :       11078 :                                                                         newextra);
    3638                 :       11078 :                                         set_guc_source(record, source);
    3639                 :       11078 :                                         record->scontext = context;
    3640                 :       11078 :                                         record->srole = srole;
    3641                 :       11078 :                                 }
    3642         [ +  + ]:       11084 :                                 if (makeDefault)
    3643                 :             :                                 {
    3644         [ -  + ]:        7319 :                                         if (record->reset_source <= source)
    3645                 :             :                                         {
    3646                 :        7319 :                                                 conf->reset_val = newval;
    3647                 :       14638 :                                                 set_extra_field(record, &record->reset_extra,
    3648                 :        7319 :                                                                                 newextra);
    3649                 :        7319 :                                                 record->reset_source = source;
    3650                 :        7319 :                                                 record->reset_scontext = context;
    3651                 :        7319 :                                                 record->reset_srole = srole;
    3652                 :        7319 :                                         }
    3653         [ -  + ]:        7319 :                                         for (GucStack *stack = record->stack; stack; stack = stack->prev)
    3654                 :             :                                         {
    3655         [ #  # ]:           0 :                                                 if (stack->source <= source)
    3656                 :             :                                                 {
    3657                 :           0 :                                                         stack->prior.val.boolval = newval;
    3658                 :           0 :                                                         set_extra_field(record, &stack->prior.extra,
    3659                 :           0 :                                                                                         newextra);
    3660                 :           0 :                                                         stack->source = source;
    3661                 :           0 :                                                         stack->scontext = context;
    3662                 :           0 :                                                         stack->srole = srole;
    3663                 :           0 :                                                 }
    3664                 :           0 :                                         }
    3665                 :        7319 :                                 }
    3666                 :             : 
    3667                 :             :                                 /* Perhaps we didn't install newextra anywhere */
    3668   [ -  +  #  # ]:       11084 :                                 if (newextra && !extra_field_used(record, newextra))
    3669                 :           0 :                                         guc_free(newextra);
    3670                 :       11084 :                                 break;
    3671                 :             : 
    3672                 :             : #undef newval
    3673                 :       11084 :                         }
    3674                 :             : 
    3675                 :             :                 case PGC_INT:
    3676                 :             :                         {
    3677                 :        4053 :                                 struct config_int *conf = &record->_int;
    3678                 :             : 
    3679                 :             : #define newval (newval_union.intval)
    3680                 :             : 
    3681         [ +  + ]:        4053 :                                 if (value)
    3682                 :             :                                 {
    3683   [ +  -  +  - ]:        7992 :                                         if (!parse_and_validate_value(record, value,
    3684                 :        3996 :                                                                                                   source, elevel,
    3685                 :             :                                                                                                   &newval_union, &newextra))
    3686                 :           0 :                                                 return 0;
    3687                 :        3996 :                                 }
    3688         [ +  - ]:          57 :                                 else if (source == PGC_S_DEFAULT)
    3689                 :             :                                 {
    3690                 :           0 :                                         newval = conf->boot_val;
    3691   [ #  #  #  # ]:           0 :                                         if (!call_int_check_hook(record, &newval, &newextra,
    3692                 :           0 :                                                                                          source, elevel))
    3693                 :           0 :                                                 return 0;
    3694                 :           0 :                                 }
    3695                 :             :                                 else
    3696                 :             :                                 {
    3697                 :          57 :                                         newval = conf->reset_val;
    3698                 :          57 :                                         newextra = record->reset_extra;
    3699                 :          57 :                                         source = record->reset_source;
    3700                 :          57 :                                         context = record->reset_scontext;
    3701                 :          57 :                                         srole = record->reset_srole;
    3702                 :             :                                 }
    3703                 :             : 
    3704         [ +  + ]:        4053 :                                 if (prohibitValueChange)
    3705                 :             :                                 {
    3706                 :             :                                         /* Release newextra, unless it's reset_extra */
    3707   [ -  +  #  # ]:           5 :                                         if (newextra && !extra_field_used(record, newextra))
    3708                 :           0 :                                                 guc_free(newextra);
    3709                 :             : 
    3710         [ -  + ]:           5 :                                         if (*conf->variable != newval)
    3711                 :             :                                         {
    3712                 :           0 :                                                 record->status |= GUC_PENDING_RESTART;
    3713   [ #  #  #  #  :           0 :                                                 ereport(elevel,
          #  #  #  #  #  
                      # ]
    3714                 :             :                                                                 (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
    3715                 :             :                                                                  errmsg("parameter \"%s\" cannot be changed without restarting the server",
    3716                 :             :                                                                                 record->name)));
    3717                 :           0 :                                                 return 0;
    3718                 :             :                                         }
    3719                 :           5 :                                         record->status &= ~GUC_PENDING_RESTART;
    3720                 :           5 :                                         return -1;
    3721                 :             :                                 }
    3722                 :             : 
    3723         [ +  + ]:        4048 :                                 if (changeVal)
    3724                 :             :                                 {
    3725                 :             :                                         /* Save old value to support transaction abort */
    3726         [ +  + ]:        4037 :                                         if (!makeDefault)
    3727                 :        1558 :                                                 push_old_value(record, action);
    3728                 :             : 
    3729         [ +  + ]:        4037 :                                         if (conf->assign_hook)
    3730                 :         970 :                                                 conf->assign_hook(newval, newextra);
    3731                 :        4037 :                                         *conf->variable = newval;
    3732                 :        8074 :                                         set_extra_field(record, &record->extra,
    3733                 :        4037 :                                                                         newextra);
    3734                 :        4037 :                                         set_guc_source(record, source);
    3735                 :        4037 :                                         record->scontext = context;
    3736                 :        4037 :                                         record->srole = srole;
    3737                 :        4037 :                                 }
    3738         [ +  + ]:        4048 :                                 if (makeDefault)
    3739                 :             :                                 {
    3740         [ -  + ]:        2479 :                                         if (record->reset_source <= source)
    3741                 :             :                                         {
    3742                 :        2479 :                                                 conf->reset_val = newval;
    3743                 :        4958 :                                                 set_extra_field(record, &record->reset_extra,
    3744                 :        2479 :                                                                                 newextra);
    3745                 :        2479 :                                                 record->reset_source = source;
    3746                 :        2479 :                                                 record->reset_scontext = context;
    3747                 :        2479 :                                                 record->reset_srole = srole;
    3748                 :        2479 :                                         }
    3749         [ -  + ]:        2479 :                                         for (GucStack *stack = record->stack; stack; stack = stack->prev)
    3750                 :             :                                         {
    3751         [ #  # ]:           0 :                                                 if (stack->source <= source)
    3752                 :             :                                                 {
    3753                 :           0 :                                                         stack->prior.val.intval = newval;
    3754                 :           0 :                                                         set_extra_field(record, &stack->prior.extra,
    3755                 :           0 :                                                                                         newextra);
    3756                 :           0 :                                                         stack->source = source;
    3757                 :           0 :                                                         stack->scontext = context;
    3758                 :           0 :                                                         stack->srole = srole;
    3759                 :           0 :                                                 }
    3760                 :           0 :                                         }
    3761                 :        2479 :                                 }
    3762                 :             : 
    3763                 :             :                                 /* Perhaps we didn't install newextra anywhere */
    3764   [ -  +  #  # ]:        4048 :                                 if (newextra && !extra_field_used(record, newextra))
    3765                 :           0 :                                         guc_free(newextra);
    3766                 :        4048 :                                 break;
    3767                 :             : 
    3768                 :             : #undef newval
    3769                 :        4053 :                         }
    3770                 :             : 
    3771                 :             :                 case PGC_REAL:
    3772                 :             :                         {
    3773                 :        1351 :                                 struct config_real *conf = &record->_real;
    3774                 :             : 
    3775                 :             : #define newval (newval_union.realval)
    3776                 :             : 
    3777         [ +  + ]:        1351 :                                 if (value)
    3778                 :             :                                 {
    3779   [ +  -  +  - ]:        2644 :                                         if (!parse_and_validate_value(record, value,
    3780                 :        1322 :                                                                                                   source, elevel,
    3781                 :             :                                                                                                   &newval_union, &newextra))
    3782                 :           0 :                                                 return 0;
    3783                 :        1322 :                                 }
    3784         [ +  - ]:          29 :                                 else if (source == PGC_S_DEFAULT)
    3785                 :             :                                 {
    3786                 :           0 :                                         newval = conf->boot_val;
    3787   [ #  #  #  # ]:           0 :                                         if (!call_real_check_hook(record, &newval, &newextra,
    3788                 :           0 :                                                                                           source, elevel))
    3789                 :           0 :                                                 return 0;
    3790                 :           0 :                                 }
    3791                 :             :                                 else
    3792                 :             :                                 {
    3793                 :          29 :                                         newval = conf->reset_val;
    3794                 :          29 :                                         newextra = record->reset_extra;
    3795                 :          29 :                                         source = record->reset_source;
    3796                 :          29 :                                         context = record->reset_scontext;
    3797                 :          29 :                                         srole = record->reset_srole;
    3798                 :             :                                 }
    3799                 :             : 
    3800         [ -  + ]:        1351 :                                 if (prohibitValueChange)
    3801                 :             :                                 {
    3802                 :             :                                         /* Release newextra, unless it's reset_extra */
    3803   [ #  #  #  # ]:           0 :                                         if (newextra && !extra_field_used(record, newextra))
    3804                 :           0 :                                                 guc_free(newextra);
    3805                 :             : 
    3806         [ #  # ]:           0 :                                         if (*conf->variable != newval)
    3807                 :             :                                         {
    3808                 :           0 :                                                 record->status |= GUC_PENDING_RESTART;
    3809   [ #  #  #  #  :           0 :                                                 ereport(elevel,
          #  #  #  #  #  
                      # ]
    3810                 :             :                                                                 (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
    3811                 :             :                                                                  errmsg("parameter \"%s\" cannot be changed without restarting the server",
    3812                 :             :                                                                                 record->name)));
    3813                 :           0 :                                                 return 0;
    3814                 :             :                                         }
    3815                 :           0 :                                         record->status &= ~GUC_PENDING_RESTART;
    3816                 :           0 :                                         return -1;
    3817                 :             :                                 }
    3818                 :             : 
    3819         [ -  + ]:        1351 :                                 if (changeVal)
    3820                 :             :                                 {
    3821                 :             :                                         /* Save old value to support transaction abort */
    3822         [ -  + ]:        1351 :                                         if (!makeDefault)
    3823                 :        1351 :                                                 push_old_value(record, action);
    3824                 :             : 
    3825         [ +  - ]:        1351 :                                         if (conf->assign_hook)
    3826                 :           0 :                                                 conf->assign_hook(newval, newextra);
    3827                 :        1351 :                                         *conf->variable = newval;
    3828                 :        2702 :                                         set_extra_field(record, &record->extra,
    3829                 :        1351 :                                                                         newextra);
    3830                 :        1351 :                                         set_guc_source(record, source);
    3831                 :        1351 :                                         record->scontext = context;
    3832                 :        1351 :                                         record->srole = srole;
    3833                 :        1351 :                                 }
    3834         [ +  - ]:        1351 :                                 if (makeDefault)
    3835                 :             :                                 {
    3836         [ #  # ]:           0 :                                         if (record->reset_source <= source)
    3837                 :             :                                         {
    3838                 :           0 :                                                 conf->reset_val = newval;
    3839                 :           0 :                                                 set_extra_field(record, &record->reset_extra,
    3840                 :           0 :                                                                                 newextra);
    3841                 :           0 :                                                 record->reset_source = source;
    3842                 :           0 :                                                 record->reset_scontext = context;
    3843                 :           0 :                                                 record->reset_srole = srole;
    3844                 :           0 :                                         }
    3845         [ #  # ]:           0 :                                         for (GucStack *stack = record->stack; stack; stack = stack->prev)
    3846                 :             :                                         {
    3847         [ #  # ]:           0 :                                                 if (stack->source <= source)
    3848                 :             :                                                 {
    3849                 :           0 :                                                         stack->prior.val.realval = newval;
    3850                 :           0 :                                                         set_extra_field(record, &stack->prior.extra,
    3851                 :           0 :                                                                                         newextra);
    3852                 :           0 :                                                         stack->source = source;
    3853                 :           0 :                                                         stack->scontext = context;
    3854                 :           0 :                                                         stack->srole = srole;
    3855                 :           0 :                                                 }
    3856                 :           0 :                                         }
    3857                 :           0 :                                 }
    3858                 :             : 
    3859                 :             :                                 /* Perhaps we didn't install newextra anywhere */
    3860   [ -  +  #  # ]:        1351 :                                 if (newextra && !extra_field_used(record, newextra))
    3861                 :           0 :                                         guc_free(newextra);
    3862                 :        1351 :                                 break;
    3863                 :             : 
    3864                 :             : #undef newval
    3865                 :        1351 :                         }
    3866                 :             : 
    3867                 :             :                 case PGC_STRING:
    3868                 :             :                         {
    3869                 :       29493 :                                 struct config_string *conf = &record->_string;
    3870                 :       29493 :                                 GucContext      orig_context = context;
    3871                 :       29493 :                                 GucSource       orig_source = source;
    3872                 :       29493 :                                 Oid                     orig_srole = srole;
    3873                 :             : 
    3874                 :             : #define newval (newval_union.stringval)
    3875                 :             : 
    3876         [ +  + ]:       29493 :                                 if (value)
    3877                 :             :                                 {
    3878   [ +  -  +  - ]:       58114 :                                         if (!parse_and_validate_value(record, value,
    3879                 :       29057 :                                                                                                   source, elevel,
    3880                 :             :                                                                                                   &newval_union, &newextra))
    3881                 :           0 :                                                 return 0;
    3882                 :       29057 :                                 }
    3883         [ +  - ]:         436 :                                 else if (source == PGC_S_DEFAULT)
    3884                 :             :                                 {
    3885                 :             :                                         /* non-NULL boot_val must always get strdup'd */
    3886         [ #  # ]:           0 :                                         if (conf->boot_val != NULL)
    3887                 :             :                                         {
    3888                 :           0 :                                                 newval = guc_strdup(elevel, conf->boot_val);
    3889         [ #  # ]:           0 :                                                 if (newval == NULL)
    3890                 :           0 :                                                         return 0;
    3891                 :           0 :                                         }
    3892                 :             :                                         else
    3893                 :           0 :                                                 newval = NULL;
    3894                 :             : 
    3895   [ #  #  #  # ]:           0 :                                         if (!call_string_check_hook(record, &newval, &newextra,
    3896                 :           0 :                                                                                                 source, elevel))
    3897                 :             :                                         {
    3898                 :           0 :                                                 guc_free(newval);
    3899                 :           0 :                                                 return 0;
    3900                 :             :                                         }
    3901                 :           0 :                                 }
    3902                 :             :                                 else
    3903                 :             :                                 {
    3904                 :             :                                         /*
    3905                 :             :                                          * strdup not needed, since reset_val is already under
    3906                 :             :                                          * guc.c's control
    3907                 :             :                                          */
    3908                 :         436 :                                         newval = conf->reset_val;
    3909                 :         436 :                                         newextra = record->reset_extra;
    3910                 :         436 :                                         source = record->reset_source;
    3911                 :         436 :                                         context = record->reset_scontext;
    3912                 :         436 :                                         srole = record->reset_srole;
    3913                 :             :                                 }
    3914                 :             : 
    3915         [ +  + ]:       29493 :                                 if (prohibitValueChange)
    3916                 :             :                                 {
    3917                 :           3 :                                         bool            newval_different;
    3918                 :             : 
    3919                 :             :                                         /* newval shouldn't be NULL, so we're a bit sloppy here */
    3920         [ +  - ]:           6 :                                         newval_different = (*conf->variable == NULL ||
    3921         [ +  - ]:           3 :                                                                                 newval == NULL ||
    3922                 :           3 :                                                                                 strcmp(*conf->variable, newval) != 0);
    3923                 :             : 
    3924                 :             :                                         /* Release newval, unless it's reset_val */
    3925   [ +  -  -  + ]:           3 :                                         if (newval && !string_field_used(record, newval))
    3926                 :           3 :                                                 guc_free(newval);
    3927                 :             :                                         /* Release newextra, unless it's reset_extra */
    3928   [ -  +  #  # ]:           3 :                                         if (newextra && !extra_field_used(record, newextra))
    3929                 :           0 :                                                 guc_free(newextra);
    3930                 :             : 
    3931         [ -  + ]:           3 :                                         if (newval_different)
    3932                 :             :                                         {
    3933                 :           0 :                                                 record->status |= GUC_PENDING_RESTART;
    3934   [ #  #  #  #  :           0 :                                                 ereport(elevel,
          #  #  #  #  #  
                      # ]
    3935                 :             :                                                                 (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
    3936                 :             :                                                                  errmsg("parameter \"%s\" cannot be changed without restarting the server",
    3937                 :             :                                                                                 record->name)));
    3938                 :           0 :                                                 return 0;
    3939                 :             :                                         }
    3940                 :           3 :                                         record->status &= ~GUC_PENDING_RESTART;
    3941                 :           3 :                                         return -1;
    3942                 :           3 :                                 }
    3943                 :             : 
    3944         [ +  + ]:       29490 :                                 if (changeVal)
    3945                 :             :                                 {
    3946                 :             :                                         /* Save old value to support transaction abort */
    3947         [ +  + ]:       29461 :                                         if (!makeDefault)
    3948                 :       15279 :                                                 push_old_value(record, action);
    3949                 :             : 
    3950         [ +  + ]:       29461 :                                         if (conf->assign_hook)
    3951                 :       27451 :                                                 conf->assign_hook(newval, newextra);
    3952                 :       29461 :                                         set_string_field(record, conf->variable, newval);
    3953                 :       58922 :                                         set_extra_field(record, &record->extra,
    3954                 :       29461 :                                                                         newextra);
    3955                 :       29461 :                                         set_guc_source(record, source);
    3956                 :       29461 :                                         record->scontext = context;
    3957                 :       29461 :                                         record->srole = srole;
    3958                 :             : 
    3959                 :             :                                         /*
    3960                 :             :                                          * Ugly hack: during SET session_authorization, forcibly
    3961                 :             :                                          * do SET ROLE NONE with the same context/source/etc, so
    3962                 :             :                                          * that the effects will have identical lifespan.  This is
    3963                 :             :                                          * required by the SQL spec, and it's not possible to do
    3964                 :             :                                          * it within the variable's check hook or assign hook
    3965                 :             :                                          * because our APIs for those don't pass enough info.
    3966                 :             :                                          * However, don't do it if is_reload: in that case we
    3967                 :             :                                          * expect that if "role" isn't supposed to be default, it
    3968                 :             :                                          * has been or will be set by a separate reload action.
    3969                 :             :                                          *
    3970                 :             :                                          * Also, for the call from InitializeSessionUserId with
    3971                 :             :                                          * source == PGC_S_OVERRIDE, use PGC_S_DYNAMIC_DEFAULT for
    3972                 :             :                                          * "role"'s source, so that it's still possible to set
    3973                 :             :                                          * "role" from pg_db_role_setting entries.  (See notes in
    3974                 :             :                                          * InitializeSessionUserId before changing this.)
    3975                 :             :                                          *
    3976                 :             :                                          * A fine point: for RESET session_authorization, we do
    3977                 :             :                                          * "RESET role" not "SET ROLE NONE" (by passing down NULL
    3978                 :             :                                          * rather than "none" for the value).  This would have the
    3979                 :             :                                          * same effects in typical cases, but if the reset value
    3980                 :             :                                          * of "role" is not "none" it seems better to revert to
    3981                 :             :                                          * that.
    3982                 :             :                                          */
    3983   [ +  +  +  + ]:       29461 :                                         if (!is_reload &&
    3984                 :       22256 :                                                 strcmp(record->name, "session_authorization") == 0)
    3985                 :         880 :                                                 (void) set_config_with_handle("role", NULL,
    3986                 :         880 :                                                                                                           value ? "none" : NULL,
    3987                 :         880 :                                                                                                           orig_context,
    3988         [ +  + ]:         880 :                                                                                                           (orig_source == PGC_S_OVERRIDE)
    3989                 :             :                                                                                                           ? PGC_S_DYNAMIC_DEFAULT
    3990                 :         564 :                                                                                                           : orig_source,
    3991                 :         880 :                                                                                                           orig_srole,
    3992                 :         880 :                                                                                                           action,
    3993                 :             :                                                                                                           true,
    3994                 :         880 :                                                                                                           elevel,
    3995                 :             :                                                                                                           false);
    3996                 :       29461 :                                 }
    3997                 :             : 
    3998         [ +  + ]:       29490 :                                 if (makeDefault)
    3999                 :             :                                 {
    4000         [ -  + ]:       14182 :                                         if (record->reset_source <= source)
    4001                 :             :                                         {
    4002                 :       14182 :                                                 set_string_field(record, &conf->reset_val, newval);
    4003                 :       28364 :                                                 set_extra_field(record, &record->reset_extra,
    4004                 :       14182 :                                                                                 newextra);
    4005                 :       14182 :                                                 record->reset_source = source;
    4006                 :       14182 :                                                 record->reset_scontext = context;
    4007                 :       14182 :                                                 record->reset_srole = srole;
    4008                 :       14182 :                                         }
    4009         [ -  + ]:       14182 :                                         for (GucStack *stack = record->stack; stack; stack = stack->prev)
    4010                 :             :                                         {
    4011         [ #  # ]:           0 :                                                 if (stack->source <= source)
    4012                 :             :                                                 {
    4013                 :           0 :                                                         set_string_field(record, &stack->prior.val.stringval,
    4014                 :           0 :                                                                                          newval);
    4015                 :           0 :                                                         set_extra_field(record, &stack->prior.extra,
    4016                 :           0 :                                                                                         newextra);
    4017                 :           0 :                                                         stack->source = source;
    4018                 :           0 :                                                         stack->scontext = context;
    4019                 :           0 :                                                         stack->srole = srole;
    4020                 :           0 :                                                 }
    4021                 :           0 :                                         }
    4022                 :       14182 :                                 }
    4023                 :             : 
    4024                 :             :                                 /* Perhaps we didn't install newval anywhere */
    4025   [ +  +  +  + ]:       29490 :                                 if (newval && !string_field_used(record, newval))
    4026                 :          29 :                                         guc_free(newval);
    4027                 :             :                                 /* Perhaps we didn't install newextra anywhere */
    4028   [ +  +  +  + ]:       29490 :                                 if (newextra && !extra_field_used(record, newextra))
    4029                 :           9 :                                         guc_free(newextra);
    4030                 :       29490 :                                 break;
    4031                 :             : 
    4032                 :             : #undef newval
    4033         [ +  + ]:       29493 :                         }
    4034                 :             : 
    4035                 :             :                 case PGC_ENUM:
    4036                 :             :                         {
    4037                 :        3340 :                                 struct config_enum *conf = &record->_enum;
    4038                 :             : 
    4039                 :             : #define newval (newval_union.enumval)
    4040                 :             : 
    4041         [ +  + ]:        3340 :                                 if (value)
    4042                 :             :                                 {
    4043   [ +  -  +  - ]:        6508 :                                         if (!parse_and_validate_value(record, value,
    4044                 :        3254 :                                                                                                   source, elevel,
    4045                 :             :                                                                                                   &newval_union, &newextra))
    4046                 :           0 :                                                 return 0;
    4047                 :        3254 :                                 }
    4048         [ +  - ]:          86 :                                 else if (source == PGC_S_DEFAULT)
    4049                 :             :                                 {
    4050                 :           0 :                                         newval = conf->boot_val;
    4051   [ #  #  #  # ]:           0 :                                         if (!call_enum_check_hook(record, &newval, &newextra,
    4052                 :           0 :                                                                                           source, elevel))
    4053                 :           0 :                                                 return 0;
    4054                 :           0 :                                 }
    4055                 :             :                                 else
    4056                 :             :                                 {
    4057                 :          86 :                                         newval = conf->reset_val;
    4058                 :          86 :                                         newextra = record->reset_extra;
    4059                 :          86 :                                         source = record->reset_source;
    4060                 :          86 :                                         context = record->reset_scontext;
    4061                 :          86 :                                         srole = record->reset_srole;
    4062                 :             :                                 }
    4063                 :             : 
    4064         [ +  + ]:        3340 :                                 if (prohibitValueChange)
    4065                 :             :                                 {
    4066                 :             :                                         /* Release newextra, unless it's reset_extra */
    4067   [ -  +  #  # ]:           2 :                                         if (newextra && !extra_field_used(record, newextra))
    4068                 :           0 :                                                 guc_free(newextra);
    4069                 :             : 
    4070         [ -  + ]:           2 :                                         if (*conf->variable != newval)
    4071                 :             :                                         {
    4072                 :           0 :                                                 record->status |= GUC_PENDING_RESTART;
    4073   [ #  #  #  #  :           0 :                                                 ereport(elevel,
          #  #  #  #  #  
                      # ]
    4074                 :             :                                                                 (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
    4075                 :             :                                                                  errmsg("parameter \"%s\" cannot be changed without restarting the server",
    4076                 :             :                                                                                 record->name)));
    4077                 :           0 :                                                 return 0;
    4078                 :             :                                         }
    4079                 :           2 :                                         record->status &= ~GUC_PENDING_RESTART;
    4080                 :           2 :                                         return -1;
    4081                 :             :                                 }
    4082                 :             : 
    4083         [ +  + ]:        3338 :                                 if (changeVal)
    4084                 :             :                                 {
    4085                 :             :                                         /* Save old value to support transaction abort */
    4086         [ +  + ]:        3333 :                                         if (!makeDefault)
    4087                 :         346 :                                                 push_old_value(record, action);
    4088                 :             : 
    4089         [ +  + ]:        3333 :                                         if (conf->assign_hook)
    4090                 :          18 :                                                 conf->assign_hook(newval, newextra);
    4091                 :        3333 :                                         *conf->variable = newval;
    4092                 :        6666 :                                         set_extra_field(record, &record->extra,
    4093                 :        3333 :                                                                         newextra);
    4094                 :        3333 :                                         set_guc_source(record, source);
    4095                 :        3333 :                                         record->scontext = context;
    4096                 :        3333 :                                         record->srole = srole;
    4097                 :        3333 :                                 }
    4098         [ +  + ]:        3338 :                                 if (makeDefault)
    4099                 :             :                                 {
    4100         [ -  + ]:        2987 :                                         if (record->reset_source <= source)
    4101                 :             :                                         {
    4102                 :        2987 :                                                 conf->reset_val = newval;
    4103                 :        5974 :                                                 set_extra_field(record, &record->reset_extra,
    4104                 :        2987 :                                                                                 newextra);
    4105                 :        2987 :                                                 record->reset_source = source;
    4106                 :        2987 :                                                 record->reset_scontext = context;
    4107                 :        2987 :                                                 record->reset_srole = srole;
    4108                 :        2987 :                                         }
    4109         [ -  + ]:        2987 :                                         for (GucStack *stack = record->stack; stack; stack = stack->prev)
    4110                 :             :                                         {
    4111         [ #  # ]:           0 :                                                 if (stack->source <= source)
    4112                 :             :                                                 {
    4113                 :           0 :                                                         stack->prior.val.enumval = newval;
    4114                 :           0 :                                                         set_extra_field(record, &stack->prior.extra,
    4115                 :           0 :                                                                                         newextra);
    4116                 :           0 :                                                         stack->source = source;
    4117                 :           0 :                                                         stack->scontext = context;
    4118                 :           0 :                                                         stack->srole = srole;
    4119                 :           0 :                                                 }
    4120                 :           0 :                                         }
    4121                 :        2987 :                                 }
    4122                 :             : 
    4123                 :             :                                 /* Perhaps we didn't install newextra anywhere */
    4124   [ -  +  #  # ]:        3338 :                                 if (newextra && !extra_field_used(record, newextra))
    4125                 :           0 :                                         guc_free(newextra);
    4126                 :        3338 :                                 break;
    4127                 :             : 
    4128                 :             : #undef newval
    4129                 :        3340 :                         }
    4130                 :             :         }
    4131                 :             : 
    4132   [ +  +  +  +  :       49311 :         if (changeVal && (record->flags & GUC_REPORT) &&
                   +  + ]
    4133                 :       24167 :                 !(record->status & GUC_NEEDS_REPORT))
    4134                 :             :         {
    4135                 :       11743 :                 record->status |= GUC_NEEDS_REPORT;
    4136                 :       11743 :                 slist_push_head(&guc_report_list, &record->report_link);
    4137                 :       11743 :         }
    4138                 :             : 
    4139                 :       49311 :         return changeVal ? 1 : -1;
    4140                 :       88924 : }
    4141                 :             : 
    4142                 :             : 
    4143                 :             : /*
    4144                 :             :  * Retrieve a config_handle for the given name, suitable for calling
    4145                 :             :  * set_config_with_handle(). Only return handle to permanent GUC.
    4146                 :             :  */
    4147                 :             : config_handle *
    4148                 :          12 : get_config_handle(const char *name)
    4149                 :             : {
    4150                 :          12 :         struct config_generic *gen = find_option(name, false, false, 0);
    4151                 :             : 
    4152   [ +  -  -  + ]:          12 :         if (gen && ((gen->flags & GUC_CUSTOM_PLACEHOLDER) == 0))
    4153                 :          12 :                 return gen;
    4154                 :             : 
    4155                 :           0 :         return NULL;
    4156                 :          12 : }
    4157                 :             : 
    4158                 :             : 
    4159                 :             : /*
    4160                 :             :  * Set the fields for source file and line number the setting came from.
    4161                 :             :  */
    4162                 :             : static void
    4163                 :        9611 : set_config_sourcefile(const char *name, char *sourcefile, int sourceline)
    4164                 :             : {
    4165                 :        9611 :         struct config_generic *record;
    4166                 :        9611 :         int                     elevel;
    4167                 :             : 
    4168                 :             :         /*
    4169                 :             :          * To avoid cluttering the log, only the postmaster bleats loudly about
    4170                 :             :          * problems with the config file.
    4171                 :             :          */
    4172                 :        9611 :         elevel = IsUnderPostmaster ? DEBUG3 : LOG;
    4173                 :             : 
    4174                 :        9611 :         record = find_option(name, true, false, elevel);
    4175                 :             :         /* should not happen */
    4176         [ +  - ]:        9611 :         if (record == NULL)
    4177                 :           0 :                 return;
    4178                 :             : 
    4179                 :        9611 :         sourcefile = guc_strdup(elevel, sourcefile);
    4180                 :        9611 :         guc_free(record->sourcefile);
    4181                 :        9611 :         record->sourcefile = sourcefile;
    4182                 :        9611 :         record->sourceline = sourceline;
    4183         [ -  + ]:        9611 : }
    4184                 :             : 
    4185                 :             : /*
    4186                 :             :  * Set a config option to the given value.
    4187                 :             :  *
    4188                 :             :  * See also set_config_option; this is just the wrapper to be called from
    4189                 :             :  * outside GUC.  (This function should be used when possible, because its API
    4190                 :             :  * is more stable than set_config_option's.)
    4191                 :             :  *
    4192                 :             :  * Note: there is no support here for setting source file/line, as it
    4193                 :             :  * is currently not needed.
    4194                 :             :  */
    4195                 :             : void
    4196                 :        7200 : SetConfigOption(const char *name, const char *value,
    4197                 :             :                                 GucContext context, GucSource source)
    4198                 :             : {
    4199                 :        7200 :         (void) set_config_option(name, value, context, source,
    4200                 :             :                                                          GUC_ACTION_SET, true, 0, false);
    4201                 :        7200 : }
    4202                 :             : 
    4203                 :             : 
    4204                 :             : 
    4205                 :             : /*
    4206                 :             :  * Fetch the current value of the option `name', as a string.
    4207                 :             :  *
    4208                 :             :  * If the option doesn't exist, return NULL if missing_ok is true,
    4209                 :             :  * otherwise throw an ereport and don't return.
    4210                 :             :  *
    4211                 :             :  * If restrict_privileged is true, we also enforce that only superusers and
    4212                 :             :  * members of the pg_read_all_settings role can see GUC_SUPERUSER_ONLY
    4213                 :             :  * variables.  This should only be passed as true in user-driven calls.
    4214                 :             :  *
    4215                 :             :  * The string is *not* allocated for modification and is really only
    4216                 :             :  * valid until the next call to configuration related functions.
    4217                 :             :  */
    4218                 :             : const char *
    4219                 :           7 : GetConfigOption(const char *name, bool missing_ok, bool restrict_privileged)
    4220                 :             : {
    4221                 :           7 :         struct config_generic *record;
    4222                 :             :         static char buffer[256];
    4223                 :             : 
    4224                 :           7 :         record = find_option(name, false, missing_ok, ERROR);
    4225         [ +  - ]:           7 :         if (record == NULL)
    4226                 :           0 :                 return NULL;
    4227   [ -  +  #  # ]:           7 :         if (restrict_privileged &&
    4228                 :           0 :                 !ConfigOptionIsVisible(record))
    4229   [ #  #  #  # ]:           0 :                 ereport(ERROR,
    4230                 :             :                                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
    4231                 :             :                                  errmsg("permission denied to examine \"%s\"", name),
    4232                 :             :                                  errdetail("Only roles with privileges of the \"%s\" role may examine this parameter.",
    4233                 :             :                                                    "pg_read_all_settings")));
    4234                 :             : 
    4235   [ -  -  -  -  :           7 :         switch (record->vartype)
                   +  + ]
    4236                 :             :         {
    4237                 :             :                 case PGC_BOOL:
    4238                 :           0 :                         return *record->_bool.variable ? "on" : "off";
    4239                 :             : 
    4240                 :             :                 case PGC_INT:
    4241                 :           0 :                         snprintf(buffer, sizeof(buffer), "%d",
    4242                 :           0 :                                          *record->_int.variable);
    4243                 :           0 :                         return buffer;
    4244                 :             : 
    4245                 :             :                 case PGC_REAL:
    4246                 :           0 :                         snprintf(buffer, sizeof(buffer), "%g",
    4247                 :           0 :                                          *record->_real.variable);
    4248                 :           0 :                         return buffer;
    4249                 :             : 
    4250                 :             :                 case PGC_STRING:
    4251         [ +  - ]:           1 :                         return *record->_string.variable ?
    4252                 :           1 :                                 *record->_string.variable : "";
    4253                 :             : 
    4254                 :             :                 case PGC_ENUM:
    4255                 :          12 :                         return config_enum_lookup_by_value(record,
    4256                 :           6 :                                                                                            *record->_enum.variable);
    4257                 :             :         }
    4258                 :           0 :         return NULL;
    4259                 :           7 : }
    4260                 :             : 
    4261                 :             : /*
    4262                 :             :  * Get the RESET value associated with the given option.
    4263                 :             :  *
    4264                 :             :  * Note: this is not re-entrant, due to use of static result buffer;
    4265                 :             :  * not to mention that a string variable could have its reset_val changed.
    4266                 :             :  * Beware of assuming the result value is good for very long.
    4267                 :             :  */
    4268                 :             : const char *
    4269                 :           0 : GetConfigOptionResetString(const char *name)
    4270                 :             : {
    4271                 :           0 :         struct config_generic *record;
    4272                 :             :         static char buffer[256];
    4273                 :             : 
    4274                 :           0 :         record = find_option(name, false, false, ERROR);
    4275         [ #  # ]:           0 :         Assert(record != NULL);
    4276         [ #  # ]:           0 :         if (!ConfigOptionIsVisible(record))
    4277   [ #  #  #  # ]:           0 :                 ereport(ERROR,
    4278                 :             :                                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
    4279                 :             :                                  errmsg("permission denied to examine \"%s\"", name),
    4280                 :             :                                  errdetail("Only roles with privileges of the \"%s\" role may examine this parameter.",
    4281                 :             :                                                    "pg_read_all_settings")));
    4282                 :             : 
    4283   [ #  #  #  #  :           0 :         switch (record->vartype)
                   #  # ]
    4284                 :             :         {
    4285                 :             :                 case PGC_BOOL:
    4286                 :           0 :                         return record->_bool.reset_val ? "on" : "off";
    4287                 :             : 
    4288                 :             :                 case PGC_INT:
    4289                 :           0 :                         snprintf(buffer, sizeof(buffer), "%d",
    4290                 :           0 :                                          record->_int.reset_val);
    4291                 :           0 :                         return buffer;
    4292                 :             : 
    4293                 :             :                 case PGC_REAL:
    4294                 :           0 :                         snprintf(buffer, sizeof(buffer), "%g",
    4295                 :           0 :                                          record->_real.reset_val);
    4296                 :           0 :                         return buffer;
    4297                 :             : 
    4298                 :             :                 case PGC_STRING:
    4299         [ #  # ]:           0 :                         return record->_string.reset_val ?
    4300                 :           0 :                                 record->_string.reset_val : "";
    4301                 :             : 
    4302                 :             :                 case PGC_ENUM:
    4303                 :           0 :                         return config_enum_lookup_by_value(record,
    4304                 :           0 :                                                                                            record->_enum.reset_val);
    4305                 :             :         }
    4306                 :           0 :         return NULL;
    4307                 :           0 : }
    4308                 :             : 
    4309                 :             : /*
    4310                 :             :  * Get the GUC flags associated with the given option.
    4311                 :             :  *
    4312                 :             :  * If the option doesn't exist, return 0 if missing_ok is true,
    4313                 :             :  * otherwise throw an ereport and don't return.
    4314                 :             :  */
    4315                 :             : int
    4316                 :           6 : GetConfigOptionFlags(const char *name, bool missing_ok)
    4317                 :             : {
    4318                 :           6 :         struct config_generic *record;
    4319                 :             : 
    4320                 :           6 :         record = find_option(name, false, missing_ok, ERROR);
    4321         [ +  - ]:           6 :         if (record == NULL)
    4322                 :           0 :                 return 0;
    4323                 :           6 :         return record->flags;
    4324                 :           6 : }
    4325                 :             : 
    4326                 :             : 
    4327                 :             : /*
    4328                 :             :  * Write updated configuration parameter values into a temporary file.
    4329                 :             :  * This function traverses the list of parameters and quotes the string
    4330                 :             :  * values before writing them.
    4331                 :             :  */
    4332                 :             : static void
    4333                 :           0 : write_auto_conf_file(int fd, const char *filename, ConfigVariable *head)
    4334                 :             : {
    4335                 :           0 :         StringInfoData buf;
    4336                 :             : 
    4337                 :           0 :         initStringInfo(&buf);
    4338                 :             : 
    4339                 :             :         /* Emit file header containing warning comment */
    4340                 :           0 :         appendStringInfoString(&buf, "# Do not edit this file manually!\n");
    4341                 :           0 :         appendStringInfoString(&buf, "# It will be overwritten by the ALTER SYSTEM command.\n");
    4342                 :             : 
    4343                 :           0 :         errno = 0;
    4344         [ #  # ]:           0 :         if (write(fd, buf.data, buf.len) != buf.len)
    4345                 :             :         {
    4346                 :             :                 /* if write didn't set errno, assume problem is no disk space */
    4347         [ #  # ]:           0 :                 if (errno == 0)
    4348                 :           0 :                         errno = ENOSPC;
    4349   [ #  #  #  # ]:           0 :                 ereport(ERROR,
    4350                 :             :                                 (errcode_for_file_access(),
    4351                 :             :                                  errmsg("could not write to file \"%s\": %m", filename)));
    4352                 :           0 :         }
    4353                 :             : 
    4354                 :             :         /* Emit each parameter, properly quoting the value */
    4355         [ #  # ]:           0 :         for (ConfigVariable *item = head; item != NULL; item = item->next)
    4356                 :             :         {
    4357                 :           0 :                 char       *escaped;
    4358                 :             : 
    4359                 :           0 :                 resetStringInfo(&buf);
    4360                 :             : 
    4361                 :           0 :                 appendStringInfoString(&buf, item->name);
    4362                 :           0 :                 appendStringInfoString(&buf, " = '");
    4363                 :             : 
    4364                 :           0 :                 escaped = escape_single_quotes_ascii(item->value);
    4365         [ #  # ]:           0 :                 if (!escaped)
    4366   [ #  #  #  # ]:           0 :                         ereport(ERROR,
    4367                 :             :                                         (errcode(ERRCODE_OUT_OF_MEMORY),
    4368                 :             :                                          errmsg("out of memory")));
    4369                 :           0 :                 appendStringInfoString(&buf, escaped);
    4370                 :           0 :                 free(escaped);
    4371                 :             : 
    4372                 :           0 :                 appendStringInfoString(&buf, "'\n");
    4373                 :             : 
    4374                 :           0 :                 errno = 0;
    4375         [ #  # ]:           0 :                 if (write(fd, buf.data, buf.len) != buf.len)
    4376                 :             :                 {
    4377                 :             :                         /* if write didn't set errno, assume problem is no disk space */
    4378         [ #  # ]:           0 :                         if (errno == 0)
    4379                 :           0 :                                 errno = ENOSPC;
    4380   [ #  #  #  # ]:           0 :                         ereport(ERROR,
    4381                 :             :                                         (errcode_for_file_access(),
    4382                 :             :                                          errmsg("could not write to file \"%s\": %m", filename)));
    4383                 :           0 :                 }
    4384                 :           0 :         }
    4385                 :             : 
    4386                 :             :         /* fsync before considering the write to be successful */
    4387         [ #  # ]:           0 :         if (pg_fsync(fd) != 0)
    4388   [ #  #  #  # ]:           0 :                 ereport(ERROR,
    4389                 :             :                                 (errcode_for_file_access(),
    4390                 :             :                                  errmsg("could not fsync file \"%s\": %m", filename)));
    4391                 :             : 
    4392                 :           0 :         pfree(buf.data);
    4393                 :           0 : }
    4394                 :             : 
    4395                 :             : /*
    4396                 :             :  * Update the given list of configuration parameters, adding, replacing
    4397                 :             :  * or deleting the entry for item "name" (delete if "value" == NULL).
    4398                 :             :  */
    4399                 :             : static void
    4400                 :           0 : replace_auto_config_value(ConfigVariable **head_p, ConfigVariable **tail_p,
    4401                 :             :                                                   const char *name, const char *value)
    4402                 :             : {
    4403                 :           0 :         ConfigVariable *newitem,
    4404                 :             :                            *next,
    4405                 :           0 :                            *prev = NULL;
    4406                 :             : 
    4407                 :             :         /*
    4408                 :             :          * Remove any existing match(es) for "name".  Normally there'd be at most
    4409                 :             :          * one, but if external tools have modified the config file, there could
    4410                 :             :          * be more.
    4411                 :             :          */
    4412         [ #  # ]:           0 :         for (ConfigVariable *item = *head_p; item != NULL; item = next)
    4413                 :             :         {
    4414                 :           0 :                 next = item->next;
    4415         [ #  # ]:           0 :                 if (guc_name_compare(item->name, name) == 0)
    4416                 :             :                 {
    4417                 :             :                         /* found a match, delete it */
    4418         [ #  # ]:           0 :                         if (prev)
    4419                 :           0 :                                 prev->next = next;
    4420                 :             :                         else
    4421                 :           0 :                                 *head_p = next;
    4422         [ #  # ]:           0 :                         if (next == NULL)
    4423                 :           0 :                                 *tail_p = prev;
    4424                 :             : 
    4425                 :           0 :                         pfree(item->name);
    4426                 :           0 :                         pfree(item->value);
    4427                 :           0 :                         pfree(item->filename);
    4428                 :           0 :                         pfree(item);
    4429                 :           0 :                 }
    4430                 :             :                 else
    4431                 :           0 :                         prev = item;
    4432                 :           0 :         }
    4433                 :             : 
    4434                 :             :         /* Done if we're trying to delete it */
    4435         [ #  # ]:           0 :         if (value == NULL)
    4436                 :           0 :                 return;
    4437                 :             : 
    4438                 :             :         /* OK, append a new entry */
    4439                 :           0 :         newitem = palloc_object(ConfigVariable);
    4440                 :           0 :         newitem->name = pstrdup(name);
    4441                 :           0 :         newitem->value = pstrdup(value);
    4442                 :           0 :         newitem->errmsg = NULL;
    4443                 :           0 :         newitem->filename = pstrdup("");   /* new item has no location */
    4444                 :           0 :         newitem->sourceline = 0;
    4445                 :           0 :         newitem->ignore = false;
    4446                 :           0 :         newitem->applied = false;
    4447                 :           0 :         newitem->next = NULL;
    4448                 :             : 
    4449         [ #  # ]:           0 :         if (*head_p == NULL)
    4450                 :           0 :                 *head_p = newitem;
    4451                 :             :         else
    4452                 :           0 :                 (*tail_p)->next = newitem;
    4453                 :           0 :         *tail_p = newitem;
    4454         [ #  # ]:           0 : }
    4455                 :             : 
    4456                 :             : 
    4457                 :             : /*
    4458                 :             :  * Execute ALTER SYSTEM statement.
    4459                 :             :  *
    4460                 :             :  * Read the old PG_AUTOCONF_FILENAME file, merge in the new variable value,
    4461                 :             :  * and write out an updated file.  If the command is ALTER SYSTEM RESET ALL,
    4462                 :             :  * we can skip reading the old file and just write an empty file.
    4463                 :             :  *
    4464                 :             :  * An LWLock is used to serialize updates of the configuration file.
    4465                 :             :  *
    4466                 :             :  * In case of an error, we leave the original automatic
    4467                 :             :  * configuration file (PG_AUTOCONF_FILENAME) intact.
    4468                 :             :  */
    4469                 :             : void
    4470                 :           0 : AlterSystemSetConfigFile(AlterSystemStmt *altersysstmt)
    4471                 :             : {
    4472                 :           0 :         char       *name;
    4473                 :           0 :         char       *value;
    4474                 :           0 :         bool            resetall = false;
    4475                 :           0 :         ConfigVariable *head = NULL;
    4476                 :           0 :         ConfigVariable *tail = NULL;
    4477                 :           0 :         volatile int Tmpfd;
    4478                 :           0 :         char            AutoConfFileName[MAXPGPATH];
    4479                 :           0 :         char            AutoConfTmpFileName[MAXPGPATH];
    4480                 :             : 
    4481                 :             :         /*
    4482                 :             :          * Extract statement arguments
    4483                 :             :          */
    4484                 :           0 :         name = altersysstmt->setstmt->name;
    4485                 :             : 
    4486         [ #  # ]:           0 :         if (!AllowAlterSystem)
    4487   [ #  #  #  # ]:           0 :                 ereport(ERROR,
    4488                 :             :                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    4489                 :             :                                  errmsg("ALTER SYSTEM is not allowed in this environment")));
    4490                 :             : 
    4491   [ #  #  #  # ]:           0 :         switch (altersysstmt->setstmt->kind)
    4492                 :             :         {
    4493                 :             :                 case VAR_SET_VALUE:
    4494                 :           0 :                         value = ExtractSetVariableArgs(altersysstmt->setstmt);
    4495                 :           0 :                         break;
    4496                 :             : 
    4497                 :             :                 case VAR_SET_DEFAULT:
    4498                 :             :                 case VAR_RESET:
    4499                 :           0 :                         value = NULL;
    4500                 :           0 :                         break;
    4501                 :             : 
    4502                 :             :                 case VAR_RESET_ALL:
    4503                 :           0 :                         value = NULL;
    4504                 :           0 :                         resetall = true;
    4505                 :           0 :                         break;
    4506                 :             : 
    4507                 :             :                 default:
    4508   [ #  #  #  # ]:           0 :                         elog(ERROR, "unrecognized alter system stmt type: %d",
    4509                 :             :                                  altersysstmt->setstmt->kind);
    4510                 :           0 :                         break;
    4511                 :             :         }
    4512                 :             : 
    4513                 :             :         /*
    4514                 :             :          * Check permission to run ALTER SYSTEM on the target variable
    4515                 :             :          */
    4516         [ #  # ]:           0 :         if (!superuser())
    4517                 :             :         {
    4518         [ #  # ]:           0 :                 if (resetall)
    4519   [ #  #  #  # ]:           0 :                         ereport(ERROR,
    4520                 :             :                                         (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
    4521                 :             :                                          errmsg("permission denied to perform ALTER SYSTEM RESET ALL")));
    4522                 :             :                 else
    4523                 :             :                 {
    4524                 :           0 :                         AclResult       aclresult;
    4525                 :             : 
    4526                 :           0 :                         aclresult = pg_parameter_aclcheck(name, GetUserId(),
    4527                 :             :                                                                                           ACL_ALTER_SYSTEM);
    4528         [ #  # ]:           0 :                         if (aclresult != ACLCHECK_OK)
    4529   [ #  #  #  # ]:           0 :                                 ereport(ERROR,
    4530                 :             :                                                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
    4531                 :             :                                                  errmsg("permission denied to set parameter \"%s\"",
    4532                 :             :                                                                 name)));
    4533                 :           0 :                 }
    4534                 :           0 :         }
    4535                 :             : 
    4536                 :             :         /*
    4537                 :             :          * Unless it's RESET_ALL, validate the target variable and value
    4538                 :             :          */
    4539         [ #  # ]:           0 :         if (!resetall)
    4540                 :             :         {
    4541                 :           0 :                 struct config_generic *record;
    4542                 :             : 
    4543                 :             :                 /* We don't want to create a placeholder if there's not one already */
    4544                 :           0 :                 record = find_option(name, false, true, DEBUG5);
    4545         [ #  # ]:           0 :                 if (record != NULL)
    4546                 :             :                 {
    4547                 :             :                         /*
    4548                 :             :                          * Don't allow parameters that can't be set in configuration files
    4549                 :             :                          * to be set in PG_AUTOCONF_FILENAME file.
    4550                 :             :                          */
    4551         [ #  # ]:           0 :                         if ((record->context == PGC_INTERNAL) ||
    4552                 :           0 :                                 (record->flags & GUC_DISALLOW_IN_FILE) ||
    4553                 :           0 :                                 (record->flags & GUC_DISALLOW_IN_AUTO_FILE))
    4554   [ #  #  #  # ]:           0 :                                 ereport(ERROR,
    4555                 :             :                                                 (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
    4556                 :             :                                                  errmsg("parameter \"%s\" cannot be changed",
    4557                 :             :                                                                 name)));
    4558                 :             : 
    4559                 :             :                         /*
    4560                 :             :                          * If a value is specified, verify that it's sane.
    4561                 :             :                          */
    4562         [ #  # ]:           0 :                         if (value)
    4563                 :             :                         {
    4564                 :           0 :                                 union config_var_val newval;
    4565                 :           0 :                                 void       *newextra = NULL;
    4566                 :             : 
    4567         [ #  # ]:           0 :                                 if (!parse_and_validate_value(record, value,
    4568                 :             :                                                                                           PGC_S_FILE, ERROR,
    4569                 :             :                                                                                           &newval, &newextra))
    4570   [ #  #  #  # ]:           0 :                                         ereport(ERROR,
    4571                 :             :                                                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    4572                 :             :                                                          errmsg("invalid value for parameter \"%s\": \"%s\"",
    4573                 :             :                                                                         name, value)));
    4574                 :             : 
    4575   [ #  #  #  # ]:           0 :                                 if (record->vartype == PGC_STRING && newval.stringval != NULL)
    4576                 :           0 :                                         guc_free(newval.stringval);
    4577                 :           0 :                                 guc_free(newextra);
    4578                 :           0 :                         }
    4579                 :           0 :                 }
    4580                 :             :                 else
    4581                 :             :                 {
    4582                 :             :                         /*
    4583                 :             :                          * Variable not known; check we'd be allowed to create it.  (We
    4584                 :             :                          * cannot validate the value, but that's fine.  A non-core GUC in
    4585                 :             :                          * the config file cannot cause postmaster start to fail, so we
    4586                 :             :                          * don't have to be too tense about possibly installing a bad
    4587                 :             :                          * value.)
    4588                 :             :                          *
    4589                 :             :                          * As an exception, we skip this check if this is a RESET command
    4590                 :             :                          * for an unknown custom GUC, else there'd be no way for users to
    4591                 :             :                          * remove such settings with reserved prefixes.
    4592                 :             :                          */
    4593   [ #  #  #  # ]:           0 :                         if (value || !valid_custom_variable_name(name))
    4594                 :           0 :                                 (void) assignable_custom_variable_name(name, false, ERROR);
    4595                 :             :                 }
    4596                 :             : 
    4597                 :             :                 /*
    4598                 :             :                  * We must also reject values containing newlines, because the grammar
    4599                 :             :                  * for config files doesn't support embedded newlines in string
    4600                 :             :                  * literals.
    4601                 :             :                  */
    4602   [ #  #  #  # ]:           0 :                 if (value && strchr(value, '\n'))
    4603   [ #  #  #  # ]:           0 :                         ereport(ERROR,
    4604                 :             :                                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    4605                 :             :                                          errmsg("parameter value for ALTER SYSTEM must not contain a newline")));
    4606                 :           0 :         }
    4607                 :             : 
    4608                 :             :         /*
    4609                 :             :          * PG_AUTOCONF_FILENAME and its corresponding temporary file are always in
    4610                 :             :          * the data directory, so we can reference them by simple relative paths.
    4611                 :             :          */
    4612                 :           0 :         snprintf(AutoConfFileName, sizeof(AutoConfFileName), "%s",
    4613                 :             :                          PG_AUTOCONF_FILENAME);
    4614                 :           0 :         snprintf(AutoConfTmpFileName, sizeof(AutoConfTmpFileName), "%s.%s",
    4615                 :           0 :                          AutoConfFileName,
    4616                 :             :                          "tmp");
    4617                 :             : 
    4618                 :             :         /*
    4619                 :             :          * Only one backend is allowed to operate on PG_AUTOCONF_FILENAME at a
    4620                 :             :          * time.  Use AutoFileLock to ensure that.  We must hold the lock while
    4621                 :             :          * reading the old file contents.
    4622                 :             :          */
    4623                 :           0 :         LWLockAcquire(AutoFileLock, LW_EXCLUSIVE);
    4624                 :             : 
    4625                 :             :         /*
    4626                 :             :          * If we're going to reset everything, then no need to open or parse the
    4627                 :             :          * old file.  We'll just write out an empty list.
    4628                 :             :          */
    4629         [ #  # ]:           0 :         if (!resetall)
    4630                 :             :         {
    4631                 :           0 :                 struct stat st;
    4632                 :             : 
    4633         [ #  # ]:           0 :                 if (stat(AutoConfFileName, &st) == 0)
    4634                 :             :                 {
    4635                 :             :                         /* open old file PG_AUTOCONF_FILENAME */
    4636                 :           0 :                         FILE       *infile;
    4637                 :             : 
    4638                 :           0 :                         infile = AllocateFile(AutoConfFileName, "r");
    4639         [ #  # ]:           0 :                         if (infile == NULL)
    4640   [ #  #  #  # ]:           0 :                                 ereport(ERROR,
    4641                 :             :                                                 (errcode_for_file_access(),
    4642                 :             :                                                  errmsg("could not open file \"%s\": %m",
    4643                 :             :                                                                 AutoConfFileName)));
    4644                 :             : 
    4645                 :             :                         /* parse it */
    4646         [ #  # ]:           0 :                         if (!ParseConfigFp(infile, AutoConfFileName, CONF_FILE_START_DEPTH,
    4647                 :             :                                                            LOG, &head, &tail))
    4648   [ #  #  #  # ]:           0 :                                 ereport(ERROR,
    4649                 :             :                                                 (errcode(ERRCODE_CONFIG_FILE_ERROR),
    4650                 :             :                                                  errmsg("could not parse contents of file \"%s\"",
    4651                 :             :                                                                 AutoConfFileName)));
    4652                 :             : 
    4653                 :           0 :                         FreeFile(infile);
    4654                 :           0 :                 }
    4655                 :             : 
    4656                 :             :                 /*
    4657                 :             :                  * Now, replace any existing entry with the new value, or add it if
    4658                 :             :                  * not present.
    4659                 :             :                  */
    4660                 :           0 :                 replace_auto_config_value(&head, &tail, name, value);
    4661                 :           0 :         }
    4662                 :             : 
    4663                 :             :         /*
    4664                 :             :          * Invoke the post-alter hook for setting this GUC variable.  GUCs
    4665                 :             :          * typically do not have corresponding entries in pg_parameter_acl, so we
    4666                 :             :          * call the hook using the name rather than a potentially-non-existent
    4667                 :             :          * OID.  Nonetheless, we pass ParameterAclRelationId so that this call
    4668                 :             :          * context can be distinguished from others.  (Note that "name" will be
    4669                 :             :          * NULL in the RESET ALL case.)
    4670                 :             :          *
    4671                 :             :          * We do this here rather than at the end, because ALTER SYSTEM is not
    4672                 :             :          * transactional.  If the hook aborts our transaction, it will be cleaner
    4673                 :             :          * to do so before we touch any files.
    4674                 :             :          */
    4675         [ #  # ]:           0 :         InvokeObjectPostAlterHookArgStr(ParameterAclRelationId, name,
    4676                 :             :                                                                         ACL_ALTER_SYSTEM,
    4677                 :             :                                                                         altersysstmt->setstmt->kind,
    4678                 :             :                                                                         false);
    4679                 :             : 
    4680                 :             :         /*
    4681                 :             :          * To ensure crash safety, first write the new file data to a temp file,
    4682                 :             :          * then atomically rename it into place.
    4683                 :             :          *
    4684                 :             :          * If there is a temp file left over due to a previous crash, it's okay to
    4685                 :             :          * truncate and reuse it.
    4686                 :             :          */
    4687                 :           0 :         Tmpfd = BasicOpenFile(AutoConfTmpFileName,
    4688                 :             :                                                   O_CREAT | O_RDWR | O_TRUNC);
    4689         [ #  # ]:           0 :         if (Tmpfd < 0)
    4690   [ #  #  #  # ]:           0 :                 ereport(ERROR,
    4691                 :             :                                 (errcode_for_file_access(),
    4692                 :             :                                  errmsg("could not open file \"%s\": %m",
    4693                 :             :                                                 AutoConfTmpFileName)));
    4694                 :             : 
    4695                 :             :         /*
    4696                 :             :          * Use a TRY block to clean up the file if we fail.  Since we need a TRY
    4697                 :             :          * block anyway, OK to use BasicOpenFile rather than OpenTransientFile.
    4698                 :             :          */
    4699         [ #  # ]:           0 :         PG_TRY();
    4700                 :             :         {
    4701                 :             :                 /* Write and sync the new contents to the temporary file */
    4702                 :           0 :                 write_auto_conf_file(Tmpfd, AutoConfTmpFileName, head);
    4703                 :             : 
    4704                 :             :                 /* Close before renaming; may be required on some platforms */
    4705                 :           0 :                 close(Tmpfd);
    4706                 :           0 :                 Tmpfd = -1;
    4707                 :             : 
    4708                 :             :                 /*
    4709                 :             :                  * As the rename is atomic operation, if any problem occurs after this
    4710                 :             :                  * at worst it can lose the parameters set by last ALTER SYSTEM
    4711                 :             :                  * command.
    4712                 :             :                  */
    4713                 :           0 :                 durable_rename(AutoConfTmpFileName, AutoConfFileName, ERROR);
    4714                 :             :         }
    4715                 :           0 :         PG_CATCH();
    4716                 :             :         {
    4717                 :             :                 /* Close file first, else unlink might fail on some platforms */
    4718         [ #  # ]:           0 :                 if (Tmpfd >= 0)
    4719                 :           0 :                         close(Tmpfd);
    4720                 :             : 
    4721                 :             :                 /* Unlink, but ignore any error */
    4722                 :           0 :                 (void) unlink(AutoConfTmpFileName);
    4723                 :             : 
    4724                 :           0 :                 PG_RE_THROW();
    4725                 :             :         }
    4726         [ #  # ]:           0 :         PG_END_TRY();
    4727                 :             : 
    4728                 :           0 :         FreeConfigVariables(head);
    4729                 :             : 
    4730                 :           0 :         LWLockRelease(AutoFileLock);
    4731                 :           0 : }
    4732                 :             : 
    4733                 :             : 
    4734                 :             : /*
    4735                 :             :  * Common code for DefineCustomXXXVariable subroutines: allocate the
    4736                 :             :  * new variable's config struct and fill in generic fields.
    4737                 :             :  */
    4738                 :             : static struct config_generic *
    4739                 :        2464 : init_custom_variable(const char *name,
    4740                 :             :                                          const char *short_desc,
    4741                 :             :                                          const char *long_desc,
    4742                 :             :                                          GucContext context,
    4743                 :             :                                          int flags,
    4744                 :             :                                          enum config_type type)
    4745                 :             : {
    4746                 :        2464 :         struct config_generic *gen;
    4747                 :             : 
    4748                 :             :         /*
    4749                 :             :          * Only allow custom PGC_POSTMASTER variables to be created during shared
    4750                 :             :          * library preload; any later than that, we can't ensure that the value
    4751                 :             :          * doesn't change after startup.  This is a fatal elog if it happens; just
    4752                 :             :          * erroring out isn't safe because we don't know what the calling loadable
    4753                 :             :          * module might already have hooked into.
    4754                 :             :          */
    4755   [ -  +  #  # ]:        2464 :         if (context == PGC_POSTMASTER &&
    4756                 :           0 :                 !process_shared_preload_libraries_in_progress)
    4757   [ #  #  #  # ]:           0 :                 elog(FATAL, "cannot create PGC_POSTMASTER variables after startup");
    4758                 :             : 
    4759                 :             :         /*
    4760                 :             :          * We can't support custom GUC_LIST_QUOTE variables, because the wrong
    4761                 :             :          * things would happen if such a variable were set or pg_dump'd when the
    4762                 :             :          * defining extension isn't loaded.  Again, treat this as fatal because
    4763                 :             :          * the loadable module may be partly initialized already.
    4764                 :             :          */
    4765         [ +  - ]:        2464 :         if (flags & GUC_LIST_QUOTE)
    4766   [ #  #  #  # ]:           0 :                 elog(FATAL, "extensions cannot define GUC_LIST_QUOTE variables");
    4767                 :             : 
    4768                 :             :         /*
    4769                 :             :          * Before pljava commit 398f3b876ed402bdaec8bc804f29e2be95c75139
    4770                 :             :          * (2015-12-15), two of that module's PGC_USERSET variables facilitated
    4771                 :             :          * trivial escalation to superuser privileges.  Restrict the variables to
    4772                 :             :          * protect sites that have yet to upgrade pljava.
    4773                 :             :          */
    4774   [ +  +  +  - ]:        4430 :         if (context == PGC_USERSET &&
    4775         [ +  - ]:        1966 :                 (strcmp(name, "pljava.classpath") == 0 ||
    4776                 :        1966 :                  strcmp(name, "pljava.vmoptions") == 0))
    4777                 :           0 :                 context = PGC_SUSET;
    4778                 :             : 
    4779                 :             :         /* As above, an OOM here is FATAL */
    4780                 :        2464 :         gen = (struct config_generic *) guc_malloc(FATAL, sizeof(struct config_generic));
    4781                 :        2464 :         memset(gen, 0, sizeof(struct config_generic));
    4782                 :             : 
    4783                 :        2464 :         gen->name = guc_strdup(FATAL, name);
    4784                 :        2464 :         gen->context = context;
    4785                 :        2464 :         gen->group = CUSTOM_OPTIONS;
    4786                 :        2464 :         gen->short_desc = short_desc;
    4787                 :        2464 :         gen->long_desc = long_desc;
    4788                 :        2464 :         gen->flags = flags;
    4789                 :        2464 :         gen->vartype = type;
    4790                 :             : 
    4791                 :        4928 :         return gen;
    4792                 :        2464 : }
    4793                 :             : 
    4794                 :             : /*
    4795                 :             :  * Common code for DefineCustomXXXVariable subroutines: insert the new
    4796                 :             :  * variable into the GUC variable hash, replacing any placeholder.
    4797                 :             :  */
    4798                 :             : static void
    4799                 :        2464 : define_custom_variable(struct config_generic *variable)
    4800                 :             : {
    4801                 :        2464 :         const char *name = variable->name;
    4802                 :        2464 :         GUCHashEntry *hentry;
    4803                 :        2464 :         struct config_generic *pHolder;
    4804                 :             : 
    4805                 :             :         /* Check mapping between initial and default value */
    4806         [ +  - ]:        2464 :         Assert(check_GUC_init(variable));
    4807                 :             : 
    4808                 :             :         /*
    4809                 :             :          * See if there's a placeholder by the same name.
    4810                 :             :          */
    4811                 :        2464 :         hentry = (GUCHashEntry *) hash_search(guc_hashtab,
    4812                 :             :                                                                                   &name,
    4813                 :             :                                                                                   HASH_FIND,
    4814                 :             :                                                                                   NULL);
    4815         [ +  + ]:        2464 :         if (hentry == NULL)
    4816                 :             :         {
    4817                 :             :                 /*
    4818                 :             :                  * No placeholder to replace, so we can just add it ... but first,
    4819                 :             :                  * make sure it's initialized to its default value.
    4820                 :             :                  */
    4821                 :        2460 :                 InitializeOneGUCOption(variable);
    4822                 :        2460 :                 add_guc_variable(variable, ERROR);
    4823                 :        2460 :                 return;
    4824                 :             :         }
    4825                 :             : 
    4826                 :             :         /*
    4827                 :             :          * This better be a placeholder
    4828                 :             :          */
    4829         [ +  - ]:           4 :         if ((hentry->gucvar->flags & GUC_CUSTOM_PLACEHOLDER) == 0)
    4830   [ #  #  #  # ]:           0 :                 ereport(ERROR,
    4831                 :             :                                 (errcode(ERRCODE_INTERNAL_ERROR),
    4832                 :             :                                  errmsg("attempt to redefine parameter \"%s\"", name)));
    4833                 :             : 
    4834         [ +  - ]:           4 :         Assert(hentry->gucvar->vartype == PGC_STRING);
    4835                 :           4 :         pHolder = hentry->gucvar;
    4836                 :             : 
    4837                 :             :         /*
    4838                 :             :          * First, set the variable to its default value.  We must do this even
    4839                 :             :          * though we intend to immediately apply a new value, since it's possible
    4840                 :             :          * that the new value is invalid.
    4841                 :             :          */
    4842                 :           4 :         InitializeOneGUCOption(variable);
    4843                 :             : 
    4844                 :             :         /*
    4845                 :             :          * Replace the placeholder in the hash table.  We aren't changing the name
    4846                 :             :          * (at least up to case-folding), so the hash value is unchanged.
    4847                 :             :          */
    4848                 :           4 :         hentry->gucname = name;
    4849                 :           4 :         hentry->gucvar = variable;
    4850                 :             : 
    4851                 :             :         /*
    4852                 :             :          * Remove the placeholder from any lists it's in, too.
    4853                 :             :          */
    4854                 :           4 :         RemoveGUCFromLists(pHolder);
    4855                 :             : 
    4856                 :             :         /*
    4857                 :             :          * Assign the string value(s) stored in the placeholder to the real
    4858                 :             :          * variable.  Essentially, we need to duplicate all the active and stacked
    4859                 :             :          * values, but with appropriate validation and datatype adjustment.
    4860                 :             :          *
    4861                 :             :          * If an assignment fails, we report a WARNING and keep going.  We don't
    4862                 :             :          * want to throw ERROR for bad values, because it'd bollix the add-on
    4863                 :             :          * module that's presumably halfway through getting loaded.  In such cases
    4864                 :             :          * the default or previous state will become active instead.
    4865                 :             :          */
    4866                 :             : 
    4867                 :             :         /* First, apply the reset value if any */
    4868         [ -  + ]:           4 :         if (pHolder->_string.reset_val)
    4869                 :           8 :                 (void) set_config_option_ext(name, pHolder->_string.reset_val,
    4870                 :           4 :                                                                          pHolder->reset_scontext,
    4871                 :           4 :                                                                          pHolder->reset_source,
    4872                 :           4 :                                                                          pHolder->reset_srole,
    4873                 :             :                                                                          GUC_ACTION_SET, true, WARNING, false);
    4874                 :             :         /* That should not have resulted in stacking anything */
    4875         [ +  - ]:           4 :         Assert(variable->stack == NULL);
    4876                 :             : 
    4877                 :             :         /* Now, apply current and stacked values, in the order they were stacked */
    4878                 :           8 :         reapply_stacked_values(variable, pHolder, pHolder->stack,
    4879                 :           4 :                                                    *(pHolder->_string.variable),
    4880                 :           4 :                                                    pHolder->scontext, pHolder->source,
    4881                 :           4 :                                                    pHolder->srole);
    4882                 :             : 
    4883                 :             :         /* Also copy over any saved source-location information */
    4884         [ -  + ]:           4 :         if (pHolder->sourcefile)
    4885                 :           8 :                 set_config_sourcefile(name, pHolder->sourcefile,
    4886                 :           4 :                                                           pHolder->sourceline);
    4887                 :             : 
    4888                 :             :         /* Now we can free the no-longer-referenced placeholder variable */
    4889                 :           4 :         free_placeholder(pHolder);
    4890         [ -  + ]:        2464 : }
    4891                 :             : 
    4892                 :             : /*
    4893                 :             :  * Recursive subroutine for define_custom_variable: reapply non-reset values
    4894                 :             :  *
    4895                 :             :  * We recurse so that the values are applied in the same order as originally.
    4896                 :             :  * At each recursion level, apply the upper-level value (passed in) in the
    4897                 :             :  * fashion implied by the stack entry.
    4898                 :             :  */
    4899                 :             : static void
    4900                 :           0 : reapply_stacked_values(struct config_generic *variable,
    4901                 :             :                                            struct config_generic *pHolder,
    4902                 :             :                                            GucStack *stack,
    4903                 :             :                                            const char *curvalue,
    4904                 :             :                                            GucContext curscontext, GucSource cursource,
    4905                 :             :                                            Oid cursrole)
    4906                 :             : {
    4907                 :           0 :         const char *name = variable->name;
    4908                 :           0 :         GucStack   *oldvarstack = variable->stack;
    4909                 :             : 
    4910         [ #  # ]:           0 :         if (stack != NULL)
    4911                 :             :         {
    4912                 :             :                 /* First, recurse, so that stack items are processed bottom to top */
    4913                 :           0 :                 reapply_stacked_values(variable, pHolder, stack->prev,
    4914                 :           0 :                                                            stack->prior.val.stringval,
    4915                 :           0 :                                                            stack->scontext, stack->source, stack->srole);
    4916                 :             : 
    4917                 :             :                 /* See how to apply the passed-in value */
    4918   [ #  #  #  #  :           0 :                 switch (stack->state)
                      # ]
    4919                 :             :                 {
    4920                 :             :                         case GUC_SAVE:
    4921                 :           0 :                                 (void) set_config_option_ext(name, curvalue,
    4922                 :           0 :                                                                                          curscontext, cursource, cursrole,
    4923                 :             :                                                                                          GUC_ACTION_SAVE, true,
    4924                 :             :                                                                                          WARNING, false);
    4925                 :           0 :                                 break;
    4926                 :             : 
    4927                 :             :                         case GUC_SET:
    4928                 :           0 :                                 (void) set_config_option_ext(name, curvalue,
    4929                 :           0 :                                                                                          curscontext, cursource, cursrole,
    4930                 :             :                                                                                          GUC_ACTION_SET, true,
    4931                 :             :                                                                                          WARNING, false);
    4932                 :           0 :                                 break;
    4933                 :             : 
    4934                 :             :                         case GUC_LOCAL:
    4935                 :           0 :                                 (void) set_config_option_ext(name, curvalue,
    4936                 :           0 :                                                                                          curscontext, cursource, cursrole,
    4937                 :             :                                                                                          GUC_ACTION_LOCAL, true,
    4938                 :             :                                                                                          WARNING, false);
    4939                 :           0 :                                 break;
    4940                 :             : 
    4941                 :             :                         case GUC_SET_LOCAL:
    4942                 :             :                                 /* first, apply the masked value as SET */
    4943                 :           0 :                                 (void) set_config_option_ext(name, stack->masked.val.stringval,
    4944                 :           0 :                                                                                          stack->masked_scontext,
    4945                 :             :                                                                                          PGC_S_SESSION,
    4946                 :           0 :                                                                                          stack->masked_srole,
    4947                 :             :                                                                                          GUC_ACTION_SET, true,
    4948                 :             :                                                                                          WARNING, false);
    4949                 :             :                                 /* then apply the current value as LOCAL */
    4950                 :           0 :                                 (void) set_config_option_ext(name, curvalue,
    4951                 :           0 :                                                                                          curscontext, cursource, cursrole,
    4952                 :             :                                                                                          GUC_ACTION_LOCAL, true,
    4953                 :             :                                                                                          WARNING, false);
    4954                 :           0 :                                 break;
    4955                 :             :                 }
    4956                 :             : 
    4957                 :             :                 /* If we successfully made a stack entry, adjust its nest level */
    4958         [ #  # ]:           0 :                 if (variable->stack != oldvarstack)
    4959                 :           0 :                         variable->stack->nest_level = stack->nest_level;
    4960                 :           0 :         }
    4961                 :             :         else
    4962                 :             :         {
    4963                 :             :                 /*
    4964                 :             :                  * We are at the end of the stack.  If the active/previous value is
    4965                 :             :                  * different from the reset value, it must represent a previously
    4966                 :             :                  * committed session value.  Apply it, and then drop the stack entry
    4967                 :             :                  * that set_config_option will have created under the impression that
    4968                 :             :                  * this is to be just a transactional assignment.  (We leak the stack
    4969                 :             :                  * entry.)
    4970                 :             :                  */
    4971         [ #  # ]:           0 :                 if (curvalue != pHolder->_string.reset_val ||
    4972         [ #  # ]:           0 :                         curscontext != pHolder->reset_scontext ||
    4973   [ #  #  #  # ]:           0 :                         cursource != pHolder->reset_source ||
    4974                 :           0 :                         cursrole != pHolder->reset_srole)
    4975                 :             :                 {
    4976                 :           0 :                         (void) set_config_option_ext(name, curvalue,
    4977                 :           0 :                                                                                  curscontext, cursource, cursrole,
    4978                 :             :                                                                                  GUC_ACTION_SET, true, WARNING, false);
    4979         [ #  # ]:           0 :                         if (variable->stack != NULL)
    4980                 :             :                         {
    4981                 :           0 :                                 slist_delete(&guc_stack_list, &variable->stack_link);
    4982                 :           0 :                                 variable->stack = NULL;
    4983                 :           0 :                         }
    4984                 :           0 :                 }
    4985                 :             :         }
    4986                 :           0 : }
    4987                 :             : 
    4988                 :             : /*
    4989                 :             :  * Free up a no-longer-referenced placeholder GUC variable.
    4990                 :             :  *
    4991                 :             :  * This neglects any stack items, so it's possible for some memory to be
    4992                 :             :  * leaked.  Since this can only happen once per session per variable, it
    4993                 :             :  * doesn't seem worth spending much code on.
    4994                 :             :  */
    4995                 :             : static void
    4996                 :           5 : free_placeholder(struct config_generic *pHolder)
    4997                 :             : {
    4998                 :             :         /* Placeholders are always STRING type, so free their values */
    4999         [ +  - ]:           5 :         Assert(pHolder->vartype == PGC_STRING);
    5000                 :           5 :         set_string_field(pHolder, pHolder->_string.variable, NULL);
    5001                 :           5 :         set_string_field(pHolder, &pHolder->_string.reset_val, NULL);
    5002                 :             : 
    5003                 :           5 :         guc_free(unconstify(char *, pHolder->name));
    5004                 :           5 :         guc_free(pHolder);
    5005                 :           5 : }
    5006                 :             : 
    5007                 :             : /*
    5008                 :             :  * Functions for extensions to call to define their custom GUC variables.
    5009                 :             :  */
    5010                 :             : void
    5011                 :        1009 : DefineCustomBoolVariable(const char *name,
    5012                 :             :                                                  const char *short_desc,
    5013                 :             :                                                  const char *long_desc,
    5014                 :             :                                                  bool *valueAddr,
    5015                 :             :                                                  bool bootValue,
    5016                 :             :                                                  GucContext context,
    5017                 :             :                                                  int flags,
    5018                 :             :                                                  GucBoolCheckHook check_hook,
    5019                 :             :                                                  GucBoolAssignHook assign_hook,
    5020                 :             :                                                  GucShowHook show_hook)
    5021                 :             : {
    5022                 :        1009 :         struct config_generic *var;
    5023                 :             : 
    5024                 :        1009 :         var = init_custom_variable(name, short_desc, long_desc, context, flags, PGC_BOOL);
    5025                 :        1009 :         var->_bool.variable = valueAddr;
    5026                 :        1009 :         var->_bool.boot_val = bootValue;
    5027                 :        1009 :         var->_bool.reset_val = bootValue;
    5028                 :        1009 :         var->_bool.check_hook = check_hook;
    5029                 :        1009 :         var->_bool.assign_hook = assign_hook;
    5030                 :        1009 :         var->_bool.show_hook = show_hook;
    5031                 :        1009 :         define_custom_variable(var);
    5032                 :        1009 : }
    5033                 :             : 
    5034                 :             : void
    5035                 :          26 : DefineCustomIntVariable(const char *name,
    5036                 :             :                                                 const char *short_desc,
    5037                 :             :                                                 const char *long_desc,
    5038                 :             :                                                 int *valueAddr,
    5039                 :             :                                                 int bootValue,
    5040                 :             :                                                 int minValue,
    5041                 :             :                                                 int maxValue,
    5042                 :             :                                                 GucContext context,
    5043                 :             :                                                 int flags,
    5044                 :             :                                                 GucIntCheckHook check_hook,
    5045                 :             :                                                 GucIntAssignHook assign_hook,
    5046                 :             :                                                 GucShowHook show_hook)
    5047                 :             : {
    5048                 :          26 :         struct config_generic *var;
    5049                 :             : 
    5050                 :          26 :         var = init_custom_variable(name, short_desc, long_desc, context, flags, PGC_INT);
    5051                 :          26 :         var->_int.variable = valueAddr;
    5052                 :          26 :         var->_int.boot_val = bootValue;
    5053                 :          26 :         var->_int.reset_val = bootValue;
    5054                 :          26 :         var->_int.min = minValue;
    5055                 :          26 :         var->_int.max = maxValue;
    5056                 :          26 :         var->_int.check_hook = check_hook;
    5057                 :          26 :         var->_int.assign_hook = assign_hook;
    5058                 :          26 :         var->_int.show_hook = show_hook;
    5059                 :          26 :         define_custom_variable(var);
    5060                 :          26 : }
    5061                 :             : 
    5062                 :             : void
    5063                 :           0 : DefineCustomRealVariable(const char *name,
    5064                 :             :                                                  const char *short_desc,
    5065                 :             :                                                  const char *long_desc,
    5066                 :             :                                                  double *valueAddr,
    5067                 :             :                                                  double bootValue,
    5068                 :             :                                                  double minValue,
    5069                 :             :                                                  double maxValue,
    5070                 :             :                                                  GucContext context,
    5071                 :             :                                                  int flags,
    5072                 :             :                                                  GucRealCheckHook check_hook,
    5073                 :             :                                                  GucRealAssignHook assign_hook,
    5074                 :             :                                                  GucShowHook show_hook)
    5075                 :             : {
    5076                 :           0 :         struct config_generic *var;
    5077                 :             : 
    5078                 :           0 :         var = init_custom_variable(name, short_desc, long_desc, context, flags, PGC_REAL);
    5079                 :           0 :         var->_real.variable = valueAddr;
    5080                 :           0 :         var->_real.boot_val = bootValue;
    5081                 :           0 :         var->_real.reset_val = bootValue;
    5082                 :           0 :         var->_real.min = minValue;
    5083                 :           0 :         var->_real.max = maxValue;
    5084                 :           0 :         var->_real.check_hook = check_hook;
    5085                 :           0 :         var->_real.assign_hook = assign_hook;
    5086                 :           0 :         var->_real.show_hook = show_hook;
    5087                 :           0 :         define_custom_variable(var);
    5088                 :           0 : }
    5089                 :             : 
    5090                 :             : void
    5091                 :         957 : DefineCustomStringVariable(const char *name,
    5092                 :             :                                                    const char *short_desc,
    5093                 :             :                                                    const char *long_desc,
    5094                 :             :                                                    char **valueAddr,
    5095                 :             :                                                    const char *bootValue,
    5096                 :             :                                                    GucContext context,
    5097                 :             :                                                    int flags,
    5098                 :             :                                                    GucStringCheckHook check_hook,
    5099                 :             :                                                    GucStringAssignHook assign_hook,
    5100                 :             :                                                    GucShowHook show_hook)
    5101                 :             : {
    5102                 :         957 :         struct config_generic *var;
    5103                 :             : 
    5104                 :         957 :         var = init_custom_variable(name, short_desc, long_desc, context, flags, PGC_STRING);
    5105                 :         957 :         var->_string.variable = valueAddr;
    5106                 :         957 :         var->_string.boot_val = bootValue;
    5107                 :         957 :         var->_string.check_hook = check_hook;
    5108                 :         957 :         var->_string.assign_hook = assign_hook;
    5109                 :         957 :         var->_string.show_hook = show_hook;
    5110                 :         957 :         define_custom_variable(var);
    5111                 :         957 : }
    5112                 :             : 
    5113                 :             : void
    5114                 :         472 : DefineCustomEnumVariable(const char *name,
    5115                 :             :                                                  const char *short_desc,
    5116                 :             :                                                  const char *long_desc,
    5117                 :             :                                                  int *valueAddr,
    5118                 :             :                                                  int bootValue,
    5119                 :             :                                                  const struct config_enum_entry *options,
    5120                 :             :                                                  GucContext context,
    5121                 :             :                                                  int flags,
    5122                 :             :                                                  GucEnumCheckHook check_hook,
    5123                 :             :                                                  GucEnumAssignHook assign_hook,
    5124                 :             :                                                  GucShowHook show_hook)
    5125                 :             : {
    5126                 :         472 :         struct config_generic *var;
    5127                 :             : 
    5128                 :         472 :         var = init_custom_variable(name, short_desc, long_desc, context, flags, PGC_ENUM);
    5129                 :         472 :         var->_enum.variable = valueAddr;
    5130                 :         472 :         var->_enum.boot_val = bootValue;
    5131                 :         472 :         var->_enum.reset_val = bootValue;
    5132                 :         472 :         var->_enum.options = options;
    5133                 :         472 :         var->_enum.check_hook = check_hook;
    5134                 :         472 :         var->_enum.assign_hook = assign_hook;
    5135                 :         472 :         var->_enum.show_hook = show_hook;
    5136                 :         472 :         define_custom_variable(var);
    5137                 :         472 : }
    5138                 :             : 
    5139                 :             : /*
    5140                 :             :  * Mark the given GUC prefix as "reserved".
    5141                 :             :  *
    5142                 :             :  * This deletes any existing placeholders matching the prefix,
    5143                 :             :  * and then prevents new ones from being created.
    5144                 :             :  * Extensions should call this after they've defined all of their custom
    5145                 :             :  * GUCs, to help catch misspelled config-file entries.
    5146                 :             :  */
    5147                 :             : void
    5148                 :         485 : MarkGUCPrefixReserved(const char *className)
    5149                 :             : {
    5150                 :         485 :         int                     classLen = strlen(className);
    5151                 :         485 :         HASH_SEQ_STATUS status;
    5152                 :         485 :         GUCHashEntry *hentry;
    5153                 :         485 :         MemoryContext oldcontext;
    5154                 :             : 
    5155                 :             :         /*
    5156                 :             :          * Check for existing placeholders.  We must actually remove invalid
    5157                 :             :          * placeholders, else future parallel worker startups will fail.
    5158                 :             :          */
    5159                 :         485 :         hash_seq_init(&status, guc_hashtab);
    5160         [ +  + ]:      206055 :         while ((hentry = (GUCHashEntry *) hash_seq_search(&status)) != NULL)
    5161                 :             :         {
    5162                 :      205570 :                 struct config_generic *var = hentry->gucvar;
    5163                 :             : 
    5164         [ +  + ]:      205570 :                 if ((var->flags & GUC_CUSTOM_PLACEHOLDER) != 0 &&
    5165   [ +  +  -  + ]:           3 :                         strncmp(className, var->name, classLen) == 0 &&
    5166                 :           1 :                         var->name[classLen] == GUC_QUALIFIER_SEPARATOR)
    5167                 :             :                 {
    5168   [ -  +  +  - ]:           1 :                         ereport(WARNING,
    5169                 :             :                                         (errcode(ERRCODE_INVALID_NAME),
    5170                 :             :                                          errmsg("invalid configuration parameter name \"%s\", removing it",
    5171                 :             :                                                         var->name),
    5172                 :             :                                          errdetail("\"%s\" is now a reserved prefix.",
    5173                 :             :                                                            className)));
    5174                 :             :                         /* Remove it from the hash table */
    5175                 :           2 :                         hash_search(guc_hashtab,
    5176                 :           1 :                                                 &var->name,
    5177                 :             :                                                 HASH_REMOVE,
    5178                 :             :                                                 NULL);
    5179                 :             :                         /* Remove it from any lists it's in, too */
    5180                 :           1 :                         RemoveGUCFromLists(var);
    5181                 :             :                         /* And free it */
    5182                 :           1 :                         free_placeholder(var);
    5183                 :           1 :                 }
    5184                 :      205570 :         }
    5185                 :             : 
    5186                 :             :         /* And remember the name so we can prevent future mistakes. */
    5187                 :         485 :         oldcontext = MemoryContextSwitchTo(GUCMemoryContext);
    5188                 :         485 :         reserved_class_prefix = lappend(reserved_class_prefix, pstrdup(className));
    5189                 :         485 :         MemoryContextSwitchTo(oldcontext);
    5190                 :         485 : }
    5191                 :             : 
    5192                 :             : 
    5193                 :             : /*
    5194                 :             :  * Return an array of modified GUC options to show in EXPLAIN.
    5195                 :             :  *
    5196                 :             :  * We only report options related to query planning (marked with GUC_EXPLAIN),
    5197                 :             :  * with values different from their built-in defaults.
    5198                 :             :  */
    5199                 :             : struct config_generic **
    5200                 :           2 : get_explain_guc_options(int *num)
    5201                 :             : {
    5202                 :           2 :         struct config_generic **result;
    5203                 :           2 :         dlist_iter      iter;
    5204                 :             : 
    5205                 :           2 :         *num = 0;
    5206                 :             : 
    5207                 :             :         /*
    5208                 :             :          * While only a fraction of all the GUC variables are marked GUC_EXPLAIN,
    5209                 :             :          * it doesn't seem worth dynamically resizing this array.
    5210                 :             :          */
    5211                 :           2 :         result = palloc_array(struct config_generic *, hash_get_num_entries(guc_hashtab));
    5212                 :             : 
    5213                 :             :         /* We need only consider GUCs with source not PGC_S_DEFAULT */
    5214   [ +  -  +  + ]:         124 :         dlist_foreach(iter, &guc_nondef_list)
    5215                 :             :         {
    5216                 :         122 :                 struct config_generic *conf = dlist_container(struct config_generic,
    5217                 :             :                                                                                                           nondef_link, iter.cur);
    5218                 :         122 :                 bool            modified;
    5219                 :             : 
    5220                 :             :                 /* return only parameters marked for inclusion in explain */
    5221         [ +  + ]:         122 :                 if (!(conf->flags & GUC_EXPLAIN))
    5222                 :         118 :                         continue;
    5223                 :             : 
    5224                 :             :                 /* return only options visible to the current user */
    5225         [ +  - ]:           4 :                 if (!ConfigOptionIsVisible(conf))
    5226                 :           0 :                         continue;
    5227                 :             : 
    5228                 :             :                 /* return only options that are different from their boot values */
    5229                 :           4 :                 modified = false;
    5230                 :             : 
    5231   [ -  +  -  -  :           4 :                 switch (conf->vartype)
                   -  + ]
    5232                 :             :                 {
    5233                 :             :                         case PGC_BOOL:
    5234                 :             :                                 {
    5235                 :           2 :                                         struct config_bool *lconf = &conf->_bool;
    5236                 :             : 
    5237                 :           2 :                                         modified = (lconf->boot_val != *(lconf->variable));
    5238                 :           2 :                                 }
    5239                 :           2 :                                 break;
    5240                 :             : 
    5241                 :             :                         case PGC_INT:
    5242                 :             :                                 {
    5243                 :           0 :                                         struct config_int *lconf = &conf->_int;
    5244                 :             : 
    5245                 :           0 :                                         modified = (lconf->boot_val != *(lconf->variable));
    5246                 :           0 :                                 }
    5247                 :           0 :                                 break;
    5248                 :             : 
    5249                 :             :                         case PGC_REAL:
    5250                 :             :                                 {
    5251                 :           0 :                                         struct config_real *lconf = &conf->_real;
    5252                 :             : 
    5253                 :           0 :                                         modified = (lconf->boot_val != *(lconf->variable));
    5254                 :           0 :                                 }
    5255                 :           0 :                                 break;
    5256                 :             : 
    5257                 :             :                         case PGC_STRING:
    5258                 :             :                                 {
    5259                 :           0 :                                         struct config_string *lconf = &conf->_string;
    5260                 :             : 
    5261   [ #  #  #  # ]:           0 :                                         if (lconf->boot_val == NULL &&
    5262                 :           0 :                                                 *lconf->variable == NULL)
    5263                 :           0 :                                                 modified = false;
    5264   [ #  #  #  # ]:           0 :                                         else if (lconf->boot_val == NULL ||
    5265                 :           0 :                                                          *lconf->variable == NULL)
    5266                 :           0 :                                                 modified = true;
    5267                 :             :                                         else
    5268                 :           0 :                                                 modified = (strcmp(lconf->boot_val, *(lconf->variable)) != 0);
    5269                 :           0 :                                 }
    5270                 :           0 :                                 break;
    5271                 :             : 
    5272                 :             :                         case PGC_ENUM:
    5273                 :             :                                 {
    5274                 :           2 :                                         struct config_enum *lconf = &conf->_enum;
    5275                 :             : 
    5276                 :           2 :                                         modified = (lconf->boot_val != *(lconf->variable));
    5277                 :           2 :                                 }
    5278                 :           2 :                                 break;
    5279                 :             : 
    5280                 :             :                         default:
    5281   [ #  #  #  # ]:           0 :                                 elog(ERROR, "unexpected GUC type: %d", conf->vartype);
    5282                 :           0 :                 }
    5283                 :             : 
    5284         [ +  - ]:           4 :                 if (!modified)
    5285                 :           0 :                         continue;
    5286                 :             : 
    5287                 :             :                 /* OK, report it */
    5288                 :           4 :                 result[*num] = conf;
    5289                 :           4 :                 *num = *num + 1;
    5290      [ -  +  + ]:         122 :         }
    5291                 :             : 
    5292                 :           4 :         return result;
    5293                 :           2 : }
    5294                 :             : 
    5295                 :             : /*
    5296                 :             :  * Return GUC variable value by name; optionally return canonical form of
    5297                 :             :  * name.  If the GUC is unset, then throw an error unless missing_ok is true,
    5298                 :             :  * in which case return NULL.  Return value is palloc'd (but *varname isn't).
    5299                 :             :  */
    5300                 :             : char *
    5301                 :         335 : GetConfigOptionByName(const char *name, const char **varname, bool missing_ok)
    5302                 :             : {
    5303                 :         335 :         struct config_generic *record;
    5304                 :             : 
    5305                 :         335 :         record = find_option(name, false, missing_ok, ERROR);
    5306         [ +  + ]:         335 :         if (record == NULL)
    5307                 :             :         {
    5308         [ +  - ]:           1 :                 if (varname)
    5309                 :           0 :                         *varname = NULL;
    5310                 :           1 :                 return NULL;
    5311                 :             :         }
    5312                 :             : 
    5313         [ +  - ]:         334 :         if (!ConfigOptionIsVisible(record))
    5314   [ #  #  #  # ]:           0 :                 ereport(ERROR,
    5315                 :             :                                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
    5316                 :             :                                  errmsg("permission denied to examine \"%s\"", name),
    5317                 :             :                                  errdetail("Only roles with privileges of the \"%s\" role may examine this parameter.",
    5318                 :             :                                                    "pg_read_all_settings")));
    5319                 :             : 
    5320         [ +  + ]:         334 :         if (varname)
    5321                 :         235 :                 *varname = record->name;
    5322                 :             : 
    5323                 :         334 :         return ShowGUCOption(record, true);
    5324                 :         335 : }
    5325                 :             : 
    5326                 :             : /*
    5327                 :             :  * ShowGUCOption: get string value of variable
    5328                 :             :  *
    5329                 :             :  * We express a numeric value in appropriate units if it has units and
    5330                 :             :  * use_units is true; else you just get the raw number.
    5331                 :             :  * The result string is palloc'd.
    5332                 :             :  */
    5333                 :             : char *
    5334                 :       16021 : ShowGUCOption(const struct config_generic *record, bool use_units)
    5335                 :             : {
    5336                 :       16021 :         char            buffer[256];
    5337                 :       16021 :         const char *val;
    5338                 :             : 
    5339   [ -  +  +  +  :       16021 :         switch (record->vartype)
                   +  + ]
    5340                 :             :         {
    5341                 :             :                 case PGC_BOOL:
    5342                 :             :                         {
    5343                 :        3657 :                                 const struct config_bool *conf = &record->_bool;
    5344                 :             : 
    5345         [ +  + ]:        3657 :                                 if (conf->show_hook)
    5346                 :         322 :                                         val = conf->show_hook();
    5347                 :             :                                 else
    5348                 :        3335 :                                         val = *conf->variable ? "on" : "off";
    5349                 :        3657 :                         }
    5350                 :        3657 :                         break;
    5351                 :             : 
    5352                 :             :                 case PGC_INT:
    5353                 :             :                         {
    5354                 :        1392 :                                 const struct config_int *conf = &record->_int;
    5355                 :             : 
    5356         [ +  + ]:        1392 :                                 if (conf->show_hook)
    5357                 :          49 :                                         val = conf->show_hook();
    5358                 :             :                                 else
    5359                 :             :                                 {
    5360                 :             :                                         /*
    5361                 :             :                                          * Use int64 arithmetic to avoid overflows in units
    5362                 :             :                                          * conversion.
    5363                 :             :                                          */
    5364                 :        1343 :                                         int64           result = *conf->variable;
    5365                 :        1343 :                                         const char *unit;
    5366                 :             : 
    5367   [ +  +  +  +  :        1343 :                                         if (use_units && result > 0 && (record->flags & GUC_UNIT))
                   +  + ]
    5368                 :          56 :                                                 convert_int_from_base_unit(result,
    5369                 :          28 :                                                                                                    record->flags & GUC_UNIT,
    5370                 :             :                                                                                                    &result, &unit);
    5371                 :             :                                         else
    5372                 :        1315 :                                                 unit = "";
    5373                 :             : 
    5374                 :        2686 :                                         snprintf(buffer, sizeof(buffer), INT64_FORMAT "%s",
    5375                 :        1343 :                                                          result, unit);
    5376                 :        1343 :                                         val = buffer;
    5377                 :        1343 :                                 }
    5378                 :        1392 :                         }
    5379                 :        1392 :                         break;
    5380                 :             : 
    5381                 :             :                 case PGC_REAL:
    5382                 :             :                         {
    5383                 :         228 :                                 const struct config_real *conf = &record->_real;
    5384                 :             : 
    5385         [ -  + ]:         228 :                                 if (conf->show_hook)
    5386                 :           0 :                                         val = conf->show_hook();
    5387                 :             :                                 else
    5388                 :             :                                 {
    5389                 :         228 :                                         double          result = *conf->variable;
    5390                 :         228 :                                         const char *unit;
    5391                 :             : 
    5392   [ +  +  +  +  :         228 :                                         if (use_units && result > 0 && (record->flags & GUC_UNIT))
                   +  - ]
    5393                 :          88 :                                                 convert_real_from_base_unit(result,
    5394                 :          44 :                                                                                                         record->flags & GUC_UNIT,
    5395                 :             :                                                                                                         &result, &unit);
    5396                 :             :                                         else
    5397                 :         184 :                                                 unit = "";
    5398                 :             : 
    5399                 :         456 :                                         snprintf(buffer, sizeof(buffer), "%g%s",
    5400                 :         228 :                                                          result, unit);
    5401                 :         228 :                                         val = buffer;
    5402                 :         228 :                                 }
    5403                 :         228 :                         }
    5404                 :         228 :                         break;
    5405                 :             : 
    5406                 :             :                 case PGC_STRING:
    5407                 :             :                         {
    5408                 :        9795 :                                 const struct config_string *conf = &record->_string;
    5409                 :             : 
    5410         [ +  + ]:        9795 :                                 if (conf->show_hook)
    5411                 :         743 :                                         val = conf->show_hook();
    5412   [ +  +  +  + ]:        9052 :                                 else if (*conf->variable && **conf->variable)
    5413                 :        8799 :                                         val = *conf->variable;
    5414                 :             :                                 else
    5415                 :         253 :                                         val = "";
    5416                 :        9795 :                         }
    5417                 :        9795 :                         break;
    5418                 :             : 
    5419                 :             :                 case PGC_ENUM:
    5420                 :             :                         {
    5421                 :         949 :                                 const struct config_enum *conf = &record->_enum;
    5422                 :             : 
    5423         [ +  + ]:         949 :                                 if (conf->show_hook)
    5424                 :           7 :                                         val = conf->show_hook();
    5425                 :             :                                 else
    5426                 :         942 :                                         val = config_enum_lookup_by_value(record, *conf->variable);
    5427                 :         949 :                         }
    5428                 :         949 :                         break;
    5429                 :             : 
    5430                 :             :                 default:
    5431                 :             :                         /* just to keep compiler quiet */
    5432                 :           0 :                         val = "???";
    5433                 :           0 :                         break;
    5434                 :             :         }
    5435                 :             : 
    5436                 :       32042 :         return pstrdup(val);
    5437                 :       16021 : }
    5438                 :             : 
    5439                 :             : 
    5440                 :             : #ifdef EXEC_BACKEND
    5441                 :             : 
    5442                 :             : /*
    5443                 :             :  *      These routines dump out all non-default GUC options into a binary
    5444                 :             :  *      file that is read by all exec'ed backends.  The format is:
    5445                 :             :  *
    5446                 :             :  *              variable name, string, null terminated
    5447                 :             :  *              variable value, string, null terminated
    5448                 :             :  *              variable sourcefile, string, null terminated (empty if none)
    5449                 :             :  *              variable sourceline, integer
    5450                 :             :  *              variable source, integer
    5451                 :             :  *              variable scontext, integer
    5452                 :             :  *              variable srole, OID
    5453                 :             :  */
    5454                 :             : static void
    5455                 :             : write_one_nondefault_variable(FILE *fp, struct config_generic *gconf)
    5456                 :             : {
    5457                 :             :         Assert(gconf->source != PGC_S_DEFAULT);
    5458                 :             : 
    5459                 :             :         fprintf(fp, "%s", gconf->name);
    5460                 :             :         fputc(0, fp);
    5461                 :             : 
    5462                 :             :         switch (gconf->vartype)
    5463                 :             :         {
    5464                 :             :                 case PGC_BOOL:
    5465                 :             :                         {
    5466                 :             :                                 struct config_bool *conf = &gconf->_bool;
    5467                 :             : 
    5468                 :             :                                 if (*conf->variable)
    5469                 :             :                                         fprintf(fp, "true");
    5470                 :             :                                 else
    5471                 :             :                                         fprintf(fp, "false");
    5472                 :             :                         }
    5473                 :             :                         break;
    5474                 :             : 
    5475                 :             :                 case PGC_INT:
    5476                 :             :                         {
    5477                 :             :                                 struct config_int *conf = &gconf->_int;
    5478                 :             : 
    5479                 :             :                                 fprintf(fp, "%d", *conf->variable);
    5480                 :             :                         }
    5481                 :             :                         break;
    5482                 :             : 
    5483                 :             :                 case PGC_REAL:
    5484                 :             :                         {
    5485                 :             :                                 struct config_real *conf = &gconf->_real;
    5486                 :             : 
    5487                 :             :                                 fprintf(fp, "%.17g", *conf->variable);
    5488                 :             :                         }
    5489                 :             :                         break;
    5490                 :             : 
    5491                 :             :                 case PGC_STRING:
    5492                 :             :                         {
    5493                 :             :                                 struct config_string *conf = &gconf->_string;
    5494                 :             : 
    5495                 :             :                                 if (*conf->variable)
    5496                 :             :                                         fprintf(fp, "%s", *conf->variable);
    5497                 :             :                         }
    5498                 :             :                         break;
    5499                 :             : 
    5500                 :             :                 case PGC_ENUM:
    5501                 :             :                         {
    5502                 :             :                                 struct config_enum *conf = &gconf->_enum;
    5503                 :             : 
    5504                 :             :                                 fprintf(fp, "%s",
    5505                 :             :                                                 config_enum_lookup_by_value(gconf, *conf->variable));
    5506                 :             :                         }
    5507                 :             :                         break;
    5508                 :             :         }
    5509                 :             : 
    5510                 :             :         fputc(0, fp);
    5511                 :             : 
    5512                 :             :         if (gconf->sourcefile)
    5513                 :             :                 fprintf(fp, "%s", gconf->sourcefile);
    5514                 :             :         fputc(0, fp);
    5515                 :             : 
    5516                 :             :         fwrite(&gconf->sourceline, 1, sizeof(gconf->sourceline), fp);
    5517                 :             :         fwrite(&gconf->source, 1, sizeof(gconf->source), fp);
    5518                 :             :         fwrite(&gconf->scontext, 1, sizeof(gconf->scontext), fp);
    5519                 :             :         fwrite(&gconf->srole, 1, sizeof(gconf->srole), fp);
    5520                 :             : }
    5521                 :             : 
    5522                 :             : void
    5523                 :             : write_nondefault_variables(GucContext context)
    5524                 :             : {
    5525                 :             :         int                     elevel;
    5526                 :             :         FILE       *fp;
    5527                 :             :         dlist_iter      iter;
    5528                 :             : 
    5529                 :             :         Assert(context == PGC_POSTMASTER || context == PGC_SIGHUP);
    5530                 :             : 
    5531                 :             :         elevel = (context == PGC_SIGHUP) ? LOG : ERROR;
    5532                 :             : 
    5533                 :             :         /*
    5534                 :             :          * Open file
    5535                 :             :          */
    5536                 :             :         fp = AllocateFile(CONFIG_EXEC_PARAMS_NEW, "w");
    5537                 :             :         if (!fp)
    5538                 :             :         {
    5539                 :             :                 ereport(elevel,
    5540                 :             :                                 (errcode_for_file_access(),
    5541                 :             :                                  errmsg("could not write to file \"%s\": %m",
    5542                 :             :                                                 CONFIG_EXEC_PARAMS_NEW)));
    5543                 :             :                 return;
    5544                 :             :         }
    5545                 :             : 
    5546                 :             :         /* We need only consider GUCs with source not PGC_S_DEFAULT */
    5547                 :             :         dlist_foreach(iter, &guc_nondef_list)
    5548                 :             :         {
    5549                 :             :                 struct config_generic *gconf = dlist_container(struct config_generic,
    5550                 :             :                                                                                                            nondef_link, iter.cur);
    5551                 :             : 
    5552                 :             :                 write_one_nondefault_variable(fp, gconf);
    5553                 :             :         }
    5554                 :             : 
    5555                 :             :         if (FreeFile(fp))
    5556                 :             :         {
    5557                 :             :                 ereport(elevel,
    5558                 :             :                                 (errcode_for_file_access(),
    5559                 :             :                                  errmsg("could not write to file \"%s\": %m",
    5560                 :             :                                                 CONFIG_EXEC_PARAMS_NEW)));
    5561                 :             :                 return;
    5562                 :             :         }
    5563                 :             : 
    5564                 :             :         /*
    5565                 :             :          * Put new file in place.  This could delay on Win32, but we don't hold
    5566                 :             :          * any exclusive locks.
    5567                 :             :          */
    5568                 :             :         rename(CONFIG_EXEC_PARAMS_NEW, CONFIG_EXEC_PARAMS);
    5569                 :             : }
    5570                 :             : 
    5571                 :             : 
    5572                 :             : /*
    5573                 :             :  *      Read string, including null byte from file
    5574                 :             :  *
    5575                 :             :  *      Return NULL on EOF and nothing read
    5576                 :             :  */
    5577                 :             : static char *
    5578                 :             : read_string_with_null(FILE *fp)
    5579                 :             : {
    5580                 :             :         int                     i = 0,
    5581                 :             :                                 ch,
    5582                 :             :                                 maxlen = 256;
    5583                 :             :         char       *str = NULL;
    5584                 :             : 
    5585                 :             :         do
    5586                 :             :         {
    5587                 :             :                 if ((ch = fgetc(fp)) == EOF)
    5588                 :             :                 {
    5589                 :             :                         if (i == 0)
    5590                 :             :                                 return NULL;
    5591                 :             :                         else
    5592                 :             :                                 elog(FATAL, "invalid format of exec config params file");
    5593                 :             :                 }
    5594                 :             :                 if (i == 0)
    5595                 :             :                         str = guc_malloc(FATAL, maxlen);
    5596                 :             :                 else if (i == maxlen)
    5597                 :             :                         str = guc_realloc(FATAL, str, maxlen *= 2);
    5598                 :             :                 str[i++] = ch;
    5599                 :             :         } while (ch != 0);
    5600                 :             : 
    5601                 :             :         return str;
    5602                 :             : }
    5603                 :             : 
    5604                 :             : 
    5605                 :             : /*
    5606                 :             :  *      This routine loads a previous postmaster dump of its non-default
    5607                 :             :  *      settings.
    5608                 :             :  */
    5609                 :             : void
    5610                 :             : read_nondefault_variables(void)
    5611                 :             : {
    5612                 :             :         FILE       *fp;
    5613                 :             :         char       *varname,
    5614                 :             :                            *varvalue,
    5615                 :             :                            *varsourcefile;
    5616                 :             :         int                     varsourceline;
    5617                 :             :         GucSource       varsource;
    5618                 :             :         GucContext      varscontext;
    5619                 :             :         Oid                     varsrole;
    5620                 :             : 
    5621                 :             :         /*
    5622                 :             :          * Open file
    5623                 :             :          */
    5624                 :             :         fp = AllocateFile(CONFIG_EXEC_PARAMS, "r");
    5625                 :             :         if (!fp)
    5626                 :             :         {
    5627                 :             :                 /* File not found is fine */
    5628                 :             :                 if (errno != ENOENT)
    5629                 :             :                         ereport(FATAL,
    5630                 :             :                                         (errcode_for_file_access(),
    5631                 :             :                                          errmsg("could not read from file \"%s\": %m",
    5632                 :             :                                                         CONFIG_EXEC_PARAMS)));
    5633                 :             :                 return;
    5634                 :             :         }
    5635                 :             : 
    5636                 :             :         for (;;)
    5637                 :             :         {
    5638                 :             :                 if ((varname = read_string_with_null(fp)) == NULL)
    5639                 :             :                         break;
    5640                 :             : 
    5641                 :             :                 if (find_option(varname, true, false, FATAL) == NULL)
    5642                 :             :                         elog(FATAL, "failed to locate variable \"%s\" in exec config params file", varname);
    5643                 :             : 
    5644                 :             :                 if ((varvalue = read_string_with_null(fp)) == NULL)
    5645                 :             :                         elog(FATAL, "invalid format of exec config params file");
    5646                 :             :                 if ((varsourcefile = read_string_with_null(fp)) == NULL)
    5647                 :             :                         elog(FATAL, "invalid format of exec config params file");
    5648                 :             :                 if (fread(&varsourceline, 1, sizeof(varsourceline), fp) != sizeof(varsourceline))
    5649                 :             :                         elog(FATAL, "invalid format of exec config params file");
    5650                 :             :                 if (fread(&varsource, 1, sizeof(varsource), fp) != sizeof(varsource))
    5651                 :             :                         elog(FATAL, "invalid format of exec config params file");
    5652                 :             :                 if (fread(&varscontext, 1, sizeof(varscontext), fp) != sizeof(varscontext))
    5653                 :             :                         elog(FATAL, "invalid format of exec config params file");
    5654                 :             :                 if (fread(&varsrole, 1, sizeof(varsrole), fp) != sizeof(varsrole))
    5655                 :             :                         elog(FATAL, "invalid format of exec config params file");
    5656                 :             : 
    5657                 :             :                 (void) set_config_option_ext(varname, varvalue,
    5658                 :             :                                                                          varscontext, varsource, varsrole,
    5659                 :             :                                                                          GUC_ACTION_SET, true, 0, true);
    5660                 :             :                 if (varsourcefile[0])
    5661                 :             :                         set_config_sourcefile(varname, varsourcefile, varsourceline);
    5662                 :             : 
    5663                 :             :                 guc_free(varname);
    5664                 :             :                 guc_free(varvalue);
    5665                 :             :                 guc_free(varsourcefile);
    5666                 :             :         }
    5667                 :             : 
    5668                 :             :         FreeFile(fp);
    5669                 :             : }
    5670                 :             : #endif                                                  /* EXEC_BACKEND */
    5671                 :             : 
    5672                 :             : /*
    5673                 :             :  * can_skip_gucvar:
    5674                 :             :  * Decide whether SerializeGUCState can skip sending this GUC variable,
    5675                 :             :  * or whether RestoreGUCState can skip resetting this GUC to default.
    5676                 :             :  *
    5677                 :             :  * It is somewhat magical and fragile that the same test works for both cases.
    5678                 :             :  * Realize in particular that we are very likely selecting different sets of
    5679                 :             :  * GUCs on the leader and worker sides!  Be sure you've understood the
    5680                 :             :  * comments here and in RestoreGUCState thoroughly before changing this.
    5681                 :             :  */
    5682                 :             : static bool
    5683                 :       45560 : can_skip_gucvar(struct config_generic *gconf)
    5684                 :             : {
    5685                 :             :         /*
    5686                 :             :          * We can skip GUCs that are guaranteed to have the same values in leaders
    5687                 :             :          * and workers.  (Note it is critical that the leader and worker have the
    5688                 :             :          * same idea of which GUCs fall into this category.  It's okay to consider
    5689                 :             :          * context and name for this purpose, since those are unchanging
    5690                 :             :          * properties of a GUC.)
    5691                 :             :          *
    5692                 :             :          * PGC_POSTMASTER variables always have the same value in every child of a
    5693                 :             :          * particular postmaster, so the worker will certainly have the right
    5694                 :             :          * value already.  Likewise, PGC_INTERNAL variables are set by special
    5695                 :             :          * mechanisms (if indeed they aren't compile-time constants).  So we may
    5696                 :             :          * always skip these.
    5697                 :             :          *
    5698                 :             :          * For all other GUCs, we skip if the GUC has its compiled-in default
    5699                 :             :          * value (i.e., source == PGC_S_DEFAULT).  On the leader side, this means
    5700                 :             :          * we don't send GUCs that have their default values, which typically
    5701                 :             :          * saves lots of work.  On the worker side, this means we don't need to
    5702                 :             :          * reset the GUC to default because it already has that value.  See
    5703                 :             :          * comments in RestoreGUCState for more info.
    5704                 :             :          */
    5705         [ +  + ]:       75407 :         return gconf->context == PGC_POSTMASTER ||
    5706         [ +  + ]:       29847 :                 gconf->context == PGC_INTERNAL ||
    5707                 :       24338 :                 gconf->source == PGC_S_DEFAULT;
    5708                 :             : }
    5709                 :             : 
    5710                 :             : /*
    5711                 :             :  * estimate_variable_size:
    5712                 :             :  *              Compute space needed for dumping the given GUC variable.
    5713                 :             :  *
    5714                 :             :  * It's OK to overestimate, but not to underestimate.
    5715                 :             :  */
    5716                 :             : static Size
    5717                 :        9910 : estimate_variable_size(struct config_generic *gconf)
    5718                 :             : {
    5719                 :        9910 :         Size            size;
    5720                 :        9910 :         Size            valsize = 0;
    5721                 :             : 
    5722                 :             :         /* Skippable GUCs consume zero space. */
    5723         [ +  + ]:        9910 :         if (can_skip_gucvar(gconf))
    5724                 :        4176 :                 return 0;
    5725                 :             : 
    5726                 :             :         /* Name, plus trailing zero byte. */
    5727                 :        5734 :         size = strlen(gconf->name) + 1;
    5728                 :             : 
    5729                 :             :         /* Get the maximum display length of the GUC value. */
    5730   [ +  +  -  +  :        5734 :         switch (gconf->vartype)
                   +  + ]
    5731                 :             :         {
    5732                 :             :                 case PGC_BOOL:
    5733                 :             :                         {
    5734                 :        1332 :                                 valsize = 5;    /* max(strlen('true'), strlen('false')) */
    5735                 :             :                         }
    5736                 :        1332 :                         break;
    5737                 :             : 
    5738                 :             :                 case PGC_INT:
    5739                 :             :                         {
    5740                 :        1101 :                                 struct config_int *conf = &gconf->_int;
    5741                 :             : 
    5742                 :             :                                 /*
    5743                 :             :                                  * Instead of getting the exact display length, use max
    5744                 :             :                                  * length.  Also reduce the max length for typical ranges of
    5745                 :             :                                  * small values.  Maximum value is 2147483647, i.e. 10 chars.
    5746                 :             :                                  * Include one byte for sign.
    5747                 :             :                                  */
    5748         [ +  + ]:        1101 :                                 if (abs(*conf->variable) < 1000)
    5749                 :         630 :                                         valsize = 3 + 1;
    5750                 :             :                                 else
    5751                 :         471 :                                         valsize = 10 + 1;
    5752                 :        1101 :                         }
    5753                 :        1101 :                         break;
    5754                 :             : 
    5755                 :             :                 case PGC_REAL:
    5756                 :             :                         {
    5757                 :             :                                 /*
    5758                 :             :                                  * We are going to print it with %e with REALTYPE_PRECISION
    5759                 :             :                                  * fractional digits.  Account for sign, leading digit,
    5760                 :             :                                  * decimal point, and exponent with up to 3 digits.  E.g.
    5761                 :             :                                  * -3.99329042340000021e+110
    5762                 :             :                                  */
    5763                 :         290 :                                 valsize = 1 + 1 + 1 + REALTYPE_PRECISION + 5;
    5764                 :             :                         }
    5765                 :         290 :                         break;
    5766                 :             : 
    5767                 :             :                 case PGC_STRING:
    5768                 :             :                         {
    5769                 :        2359 :                                 struct config_string *conf = &gconf->_string;
    5770                 :             : 
    5771                 :             :                                 /*
    5772                 :             :                                  * If the value is NULL, we transmit it as an empty string.
    5773                 :             :                                  * Although this is not physically the same value, GUC
    5774                 :             :                                  * generally treats a NULL the same as empty string.
    5775                 :             :                                  */
    5776         [ +  - ]:        2359 :                                 if (*conf->variable)
    5777                 :        2359 :                                         valsize = strlen(*conf->variable);
    5778                 :             :                                 else
    5779                 :           0 :                                         valsize = 0;
    5780                 :        2359 :                         }
    5781                 :        2359 :                         break;
    5782                 :             : 
    5783                 :             :                 case PGC_ENUM:
    5784                 :             :                         {
    5785                 :         652 :                                 struct config_enum *conf = &gconf->_enum;
    5786                 :             : 
    5787                 :         652 :                                 valsize = strlen(config_enum_lookup_by_value(gconf, *conf->variable));
    5788                 :         652 :                         }
    5789                 :         652 :                         break;
    5790                 :             :         }
    5791                 :             : 
    5792                 :             :         /* Allow space for terminating zero-byte for value */
    5793                 :        5734 :         size = add_size(size, valsize + 1);
    5794                 :             : 
    5795         [ +  + ]:        5734 :         if (gconf->sourcefile)
    5796                 :        3088 :                 size = add_size(size, strlen(gconf->sourcefile));
    5797                 :             : 
    5798                 :             :         /* Allow space for terminating zero-byte for sourcefile */
    5799                 :        5734 :         size = add_size(size, 1);
    5800                 :             : 
    5801                 :             :         /* Include line whenever file is nonempty. */
    5802   [ +  +  -  + ]:        5734 :         if (gconf->sourcefile && gconf->sourcefile[0])
    5803                 :        3088 :                 size = add_size(size, sizeof(gconf->sourceline));
    5804                 :             : 
    5805                 :        5734 :         size = add_size(size, sizeof(gconf->source));
    5806                 :        5734 :         size = add_size(size, sizeof(gconf->scontext));
    5807                 :        5734 :         size = add_size(size, sizeof(gconf->srole));
    5808                 :             : 
    5809                 :        5734 :         return size;
    5810                 :        9910 : }
    5811                 :             : 
    5812                 :             : /*
    5813                 :             :  * EstimateGUCStateSpace:
    5814                 :             :  * Returns the size needed to store the GUC state for the current process
    5815                 :             :  */
    5816                 :             : Size
    5817                 :         155 : EstimateGUCStateSpace(void)
    5818                 :             : {
    5819                 :         155 :         Size            size;
    5820                 :         155 :         dlist_iter      iter;
    5821                 :             : 
    5822                 :             :         /* Add space reqd for saving the data size of the guc state */
    5823                 :         155 :         size = sizeof(Size);
    5824                 :             : 
    5825                 :             :         /*
    5826                 :             :          * Add up the space needed for each GUC variable.
    5827                 :             :          *
    5828                 :             :          * We need only process non-default GUCs.
    5829                 :             :          */
    5830   [ +  -  +  + ]:       10065 :         dlist_foreach(iter, &guc_nondef_list)
    5831                 :             :         {
    5832                 :        9910 :                 struct config_generic *gconf = dlist_container(struct config_generic,
    5833                 :             :                                                                                                            nondef_link, iter.cur);
    5834                 :             : 
    5835                 :        9910 :                 size = add_size(size, estimate_variable_size(gconf));
    5836                 :        9910 :         }
    5837                 :             : 
    5838                 :         310 :         return size;
    5839                 :         155 : }
    5840                 :             : 
    5841                 :             : /*
    5842                 :             :  * do_serialize:
    5843                 :             :  * Copies the formatted string into the destination.  Moves ahead the
    5844                 :             :  * destination pointer, and decrements the maxbytes by that many bytes. If
    5845                 :             :  * maxbytes is not sufficient to copy the string, error out.
    5846                 :             :  */
    5847                 :             : static void
    5848                 :           0 : do_serialize(char **destptr, Size *maxbytes, const char *fmt,...)
    5849                 :             : {
    5850                 :           0 :         va_list         vargs;
    5851                 :           0 :         int                     n;
    5852                 :             : 
    5853         [ #  # ]:           0 :         if (*maxbytes <= 0)
    5854   [ #  #  #  # ]:           0 :                 elog(ERROR, "not enough space to serialize GUC state");
    5855                 :             : 
    5856                 :           0 :         va_start(vargs, fmt);
    5857                 :           0 :         n = vsnprintf(*destptr, *maxbytes, fmt, vargs);
    5858                 :           0 :         va_end(vargs);
    5859                 :             : 
    5860         [ #  # ]:           0 :         if (n < 0)
    5861                 :             :         {
    5862                 :             :                 /* Shouldn't happen. Better show errno description. */
    5863   [ #  #  #  # ]:           0 :                 elog(ERROR, "vsnprintf failed: %m with format string \"%s\"", fmt);
    5864                 :           0 :         }
    5865         [ #  # ]:           0 :         if (n >= *maxbytes)
    5866                 :             :         {
    5867                 :             :                 /* This shouldn't happen either, really. */
    5868   [ #  #  #  # ]:           0 :                 elog(ERROR, "not enough space to serialize GUC state");
    5869                 :           0 :         }
    5870                 :             : 
    5871                 :             :         /* Shift the destptr ahead of the null terminator */
    5872                 :           0 :         *destptr += n + 1;
    5873                 :           0 :         *maxbytes -= n + 1;
    5874                 :           0 : }
    5875                 :             : 
    5876                 :             : /* Binary copy version of do_serialize() */
    5877                 :             : static void
    5878                 :           0 : do_serialize_binary(char **destptr, Size *maxbytes, void *val, Size valsize)
    5879                 :             : {
    5880         [ #  # ]:           0 :         if (valsize > *maxbytes)
    5881   [ #  #  #  # ]:           0 :                 elog(ERROR, "not enough space to serialize GUC state");
    5882                 :             : 
    5883                 :           0 :         memcpy(*destptr, val, valsize);
    5884                 :           0 :         *destptr += valsize;
    5885                 :           0 :         *maxbytes -= valsize;
    5886                 :           0 : }
    5887                 :             : 
    5888                 :             : /*
    5889                 :             :  * serialize_variable:
    5890                 :             :  * Dumps name, value and other information of a GUC variable into destptr.
    5891                 :             :  */
    5892                 :             : static void
    5893                 :        9910 : serialize_variable(char **destptr, Size *maxbytes,
    5894                 :             :                                    struct config_generic *gconf)
    5895                 :             : {
    5896                 :             :         /* Ignore skippable GUCs. */
    5897         [ +  + ]:        9910 :         if (can_skip_gucvar(gconf))
    5898                 :        4176 :                 return;
    5899                 :             : 
    5900                 :        5734 :         do_serialize(destptr, maxbytes, "%s", gconf->name);
    5901                 :             : 
    5902   [ +  +  +  -  :        5734 :         switch (gconf->vartype)
                   +  + ]
    5903                 :             :         {
    5904                 :             :                 case PGC_BOOL:
    5905                 :             :                         {
    5906                 :        1332 :                                 struct config_bool *conf = &gconf->_bool;
    5907                 :             : 
    5908                 :        2664 :                                 do_serialize(destptr, maxbytes,
    5909                 :        1332 :                                                          (*conf->variable ? "true" : "false"));
    5910                 :        1332 :                         }
    5911                 :        1332 :                         break;
    5912                 :             : 
    5913                 :             :                 case PGC_INT:
    5914                 :             :                         {
    5915                 :        1101 :                                 struct config_int *conf = &gconf->_int;
    5916                 :             : 
    5917                 :        1101 :                                 do_serialize(destptr, maxbytes, "%d", *conf->variable);
    5918                 :        1101 :                         }
    5919                 :        1101 :                         break;
    5920                 :             : 
    5921                 :             :                 case PGC_REAL:
    5922                 :             :                         {
    5923                 :         290 :                                 struct config_real *conf = &gconf->_real;
    5924                 :             : 
    5925                 :         580 :                                 do_serialize(destptr, maxbytes, "%.*e",
    5926                 :         290 :                                                          REALTYPE_PRECISION, *conf->variable);
    5927                 :         290 :                         }
    5928                 :         290 :                         break;
    5929                 :             : 
    5930                 :             :                 case PGC_STRING:
    5931                 :             :                         {
    5932                 :        2359 :                                 struct config_string *conf = &gconf->_string;
    5933                 :             : 
    5934                 :             :                                 /* NULL becomes empty string, see estimate_variable_size() */
    5935                 :        4718 :                                 do_serialize(destptr, maxbytes, "%s",
    5936         [ +  - ]:        2359 :                                                          *conf->variable ? *conf->variable : "");
    5937                 :        2359 :                         }
    5938                 :        2359 :                         break;
    5939                 :             : 
    5940                 :             :                 case PGC_ENUM:
    5941                 :             :                         {
    5942                 :         652 :                                 struct config_enum *conf = &gconf->_enum;
    5943                 :             : 
    5944                 :        1304 :                                 do_serialize(destptr, maxbytes, "%s",
    5945                 :         652 :                                                          config_enum_lookup_by_value(gconf, *conf->variable));
    5946                 :         652 :                         }
    5947                 :         652 :                         break;
    5948                 :             :         }
    5949                 :             : 
    5950                 :       11468 :         do_serialize(destptr, maxbytes, "%s",
    5951         [ +  + ]:        5734 :                                  (gconf->sourcefile ? gconf->sourcefile : ""));
    5952                 :             : 
    5953   [ +  +  -  + ]:        5734 :         if (gconf->sourcefile && gconf->sourcefile[0])
    5954                 :        3088 :                 do_serialize_binary(destptr, maxbytes, &gconf->sourceline,
    5955                 :             :                                                         sizeof(gconf->sourceline));
    5956                 :             : 
    5957                 :        5734 :         do_serialize_binary(destptr, maxbytes, &gconf->source,
    5958                 :             :                                                 sizeof(gconf->source));
    5959                 :        5734 :         do_serialize_binary(destptr, maxbytes, &gconf->scontext,
    5960                 :             :                                                 sizeof(gconf->scontext));
    5961                 :        5734 :         do_serialize_binary(destptr, maxbytes, &gconf->srole,
    5962                 :             :                                                 sizeof(gconf->srole));
    5963                 :        9910 : }
    5964                 :             : 
    5965                 :             : /*
    5966                 :             :  * SerializeGUCState:
    5967                 :             :  * Dumps the complete GUC state onto the memory location at start_address.
    5968                 :             :  */
    5969                 :             : void
    5970                 :         155 : SerializeGUCState(Size maxsize, char *start_address)
    5971                 :             : {
    5972                 :         155 :         char       *curptr;
    5973                 :         155 :         Size            actual_size;
    5974                 :         155 :         Size            bytes_left;
    5975                 :         155 :         dlist_iter      iter;
    5976                 :             : 
    5977                 :             :         /* Reserve space for saving the actual size of the guc state */
    5978         [ +  - ]:         155 :         Assert(maxsize > sizeof(actual_size));
    5979                 :         155 :         curptr = start_address + sizeof(actual_size);
    5980                 :         155 :         bytes_left = maxsize - sizeof(actual_size);
    5981                 :             : 
    5982                 :             :         /* We need only consider GUCs with source not PGC_S_DEFAULT */
    5983   [ +  -  +  + ]:       10065 :         dlist_foreach(iter, &guc_nondef_list)
    5984                 :             :         {
    5985                 :        9910 :                 struct config_generic *gconf = dlist_container(struct config_generic,
    5986                 :             :                                                                                                            nondef_link, iter.cur);
    5987                 :             : 
    5988                 :        9910 :                 serialize_variable(&curptr, &bytes_left, gconf);
    5989                 :        9910 :         }
    5990                 :             : 
    5991                 :             :         /* Store actual size without assuming alignment of start_address. */
    5992                 :         155 :         actual_size = maxsize - bytes_left - sizeof(actual_size);
    5993                 :         155 :         memcpy(start_address, &actual_size, sizeof(actual_size));
    5994                 :         155 : }
    5995                 :             : 
    5996                 :             : /*
    5997                 :             :  * read_gucstate:
    5998                 :             :  * Actually it does not read anything, just returns the srcptr. But it does
    5999                 :             :  * move the srcptr past the terminating zero byte, so that the caller is ready
    6000                 :             :  * to read the next string.
    6001                 :             :  */
    6002                 :             : static char *
    6003                 :       54918 : read_gucstate(char **srcptr, char *srcend)
    6004                 :             : {
    6005                 :       54918 :         char       *retptr = *srcptr;
    6006                 :       54918 :         char       *ptr;
    6007                 :             : 
    6008         [ +  - ]:       54918 :         if (*srcptr >= srcend)
    6009   [ #  #  #  # ]:           0 :                 elog(ERROR, "incomplete GUC state");
    6010                 :             : 
    6011                 :             :         /* The string variables are all null terminated */
    6012   [ -  +  +  + ]:     1618736 :         for (ptr = *srcptr; ptr < srcend && *ptr != '\0'; ptr++)
    6013                 :             :                 ;
    6014                 :             : 
    6015         [ +  - ]:       54918 :         if (ptr >= srcend)
    6016   [ #  #  #  # ]:           0 :                 elog(ERROR, "could not find null terminator in GUC state");
    6017                 :             : 
    6018                 :             :         /* Set the new position to the byte following the terminating NUL */
    6019                 :       54918 :         *srcptr = ptr + 1;
    6020                 :             : 
    6021                 :      109836 :         return retptr;
    6022                 :       54918 : }
    6023                 :             : 
    6024                 :             : /* Binary read version of read_gucstate(). Copies into dest */
    6025                 :             : static void
    6026                 :       64446 : read_gucstate_binary(char **srcptr, char *srcend, void *dest, Size size)
    6027                 :             : {
    6028         [ +  - ]:       64446 :         if (*srcptr + size > srcend)
    6029   [ #  #  #  # ]:           0 :                 elog(ERROR, "incomplete GUC state");
    6030                 :             : 
    6031                 :       64446 :         memcpy(dest, *srcptr, size);
    6032                 :       64446 :         *srcptr += size;
    6033                 :       64446 : }
    6034                 :             : 
    6035                 :             : /*
    6036                 :             :  * Callback used to add a context message when reporting errors that occur
    6037                 :             :  * while trying to restore GUCs in parallel workers.
    6038                 :             :  */
    6039                 :             : static void
    6040                 :           0 : guc_restore_error_context_callback(void *arg)
    6041                 :             : {
    6042                 :           0 :         char      **error_context_name_and_value = (char **) arg;
    6043                 :             : 
    6044         [ #  # ]:           0 :         if (error_context_name_and_value)
    6045                 :           0 :                 errcontext("while setting parameter \"%s\" to \"%s\"",
    6046                 :           0 :                                    error_context_name_and_value[0],
    6047                 :           0 :                                    error_context_name_and_value[1]);
    6048                 :           0 : }
    6049                 :             : 
    6050                 :             : /*
    6051                 :             :  * RestoreGUCState:
    6052                 :             :  * Reads the GUC state at the specified address and sets this process's
    6053                 :             :  * GUCs to match.
    6054                 :             :  *
    6055                 :             :  * Note that this provides the worker with only a very shallow view of the
    6056                 :             :  * leader's GUC state: we'll know about the currently active values, but not
    6057                 :             :  * about stacked or reset values.  That's fine since the worker is just
    6058                 :             :  * executing one part of a query, within which the active values won't change
    6059                 :             :  * and the stacked values are invisible.
    6060                 :             :  */
    6061                 :             : void
    6062                 :         477 : RestoreGUCState(void *gucstate)
    6063                 :             : {
    6064                 :         477 :         char       *varname,
    6065                 :             :                            *varvalue,
    6066                 :             :                            *varsourcefile;
    6067                 :         477 :         int                     varsourceline;
    6068                 :         477 :         GucSource       varsource;
    6069                 :         477 :         GucContext      varscontext;
    6070                 :         477 :         Oid                     varsrole;
    6071                 :         477 :         char       *srcptr = (char *) gucstate;
    6072                 :         477 :         char       *srcend;
    6073                 :         477 :         Size            len;
    6074                 :         477 :         dlist_mutable_iter iter;
    6075                 :         477 :         ErrorContextCallback error_context_callback;
    6076                 :             : 
    6077                 :             :         /*
    6078                 :             :          * First, ensure that all potentially-shippable GUCs are reset to their
    6079                 :             :          * default values.  We must not touch those GUCs that the leader will
    6080                 :             :          * never ship, while there is no need to touch those that are shippable
    6081                 :             :          * but already have their default values.  Thus, this ends up being the
    6082                 :             :          * same test that SerializeGUCState uses, even though the sets of
    6083                 :             :          * variables involved may well be different since the leader's set of
    6084                 :             :          * variables-not-at-default-values can differ from the set that are
    6085                 :             :          * not-default in this freshly started worker.
    6086                 :             :          *
    6087                 :             :          * Once we have set all the potentially-shippable GUCs to default values,
    6088                 :             :          * restoring the GUCs that the leader sent (because they had non-default
    6089                 :             :          * values over there) leads us to exactly the set of GUC values that the
    6090                 :             :          * leader has.  This is true even though the worker may have initially
    6091                 :             :          * absorbed postgresql.conf settings that the leader hasn't yet seen, or
    6092                 :             :          * ALTER USER/DATABASE SET settings that were established after the leader
    6093                 :             :          * started.
    6094                 :             :          *
    6095                 :             :          * Note that ensuring all the potential target GUCs are at PGC_S_DEFAULT
    6096                 :             :          * also ensures that set_config_option won't refuse to set them because of
    6097                 :             :          * source-priority comparisons.
    6098                 :             :          */
    6099   [ +  -  +  + ]:       26217 :         dlist_foreach_modify(iter, &guc_nondef_list)
    6100                 :             :         {
    6101                 :       25740 :                 struct config_generic *gconf = dlist_container(struct config_generic,
    6102                 :             :                                                                                                            nondef_link, iter.cur);
    6103                 :             : 
    6104                 :             :                 /* Do nothing if non-shippable or if already at PGC_S_DEFAULT. */
    6105         [ +  + ]:       25740 :                 if (can_skip_gucvar(gconf))
    6106                 :       12870 :                         continue;
    6107                 :             : 
    6108                 :             :                 /*
    6109                 :             :                  * We can use InitializeOneGUCOption to reset the GUC to default, but
    6110                 :             :                  * first we must free any existing subsidiary data to avoid leaking
    6111                 :             :                  * memory.  The stack must be empty, but we have to clean up all other
    6112                 :             :                  * fields.  Beware that there might be duplicate value or "extra"
    6113                 :             :                  * pointers.  We also have to be sure to take it out of any lists it's
    6114                 :             :                  * in.
    6115                 :             :                  */
    6116         [ -  + ]:       12870 :                 Assert(gconf->stack == NULL);
    6117                 :       12870 :                 guc_free(gconf->extra);
    6118                 :       12870 :                 guc_free(gconf->last_reported);
    6119                 :       12870 :                 guc_free(gconf->sourcefile);
    6120      [ +  -  + ]:       12870 :                 switch (gconf->vartype)
    6121                 :             :                 {
    6122                 :             :                         case PGC_BOOL:
    6123                 :             :                         case PGC_INT:
    6124                 :             :                         case PGC_REAL:
    6125                 :             :                         case PGC_ENUM:
    6126                 :             :                                 /* no need to do anything */
    6127                 :        7149 :                                 break;
    6128                 :             :                         case PGC_STRING:
    6129                 :             :                                 {
    6130                 :        5721 :                                         struct config_string *conf = &gconf->_string;
    6131                 :             : 
    6132                 :        5721 :                                         guc_free(*conf->variable);
    6133   [ +  -  +  - ]:        5721 :                                         if (conf->reset_val && conf->reset_val != *conf->variable)
    6134                 :           0 :                                                 guc_free(conf->reset_val);
    6135                 :             :                                         break;
    6136                 :        5721 :                                 }
    6137                 :             :                 }
    6138   [ +  +  +  - ]:       12870 :                 if (gconf->reset_extra && gconf->reset_extra != gconf->extra)
    6139                 :           0 :                         guc_free(gconf->reset_extra);
    6140                 :             :                 /* Remove it from any lists it's in. */
    6141                 :       12870 :                 RemoveGUCFromLists(gconf);
    6142                 :             :                 /* Now we can reset the struct to PGS_S_DEFAULT state. */
    6143                 :       12870 :                 InitializeOneGUCOption(gconf);
    6144      [ -  +  + ]:       25740 :         }
    6145                 :             : 
    6146                 :             :         /* First item is the length of the subsequent data */
    6147                 :         477 :         memcpy(&len, gucstate, sizeof(len));
    6148                 :             : 
    6149                 :         477 :         srcptr += sizeof(len);
    6150                 :         477 :         srcend = srcptr + len;
    6151                 :             : 
    6152                 :             :         /* If the GUC value check fails, we want errors to show useful context. */
    6153                 :         477 :         error_context_callback.callback = guc_restore_error_context_callback;
    6154                 :         477 :         error_context_callback.previous = error_context_stack;
    6155                 :         477 :         error_context_callback.arg = NULL;
    6156                 :         477 :         error_context_stack = &error_context_callback;
    6157                 :             : 
    6158                 :             :         /* Restore all the listed GUCs. */
    6159         [ +  + ]:       18783 :         while (srcptr < srcend)
    6160                 :             :         {
    6161                 :       18306 :                 int                     result;
    6162                 :       18306 :                 char       *error_context_name_and_value[2];
    6163                 :             : 
    6164                 :       18306 :                 varname = read_gucstate(&srcptr, srcend);
    6165                 :       18306 :                 varvalue = read_gucstate(&srcptr, srcend);
    6166                 :       18306 :                 varsourcefile = read_gucstate(&srcptr, srcend);
    6167         [ +  + ]:       18306 :                 if (varsourcefile[0])
    6168                 :        9528 :                         read_gucstate_binary(&srcptr, srcend,
    6169                 :             :                                                                  &varsourceline, sizeof(varsourceline));
    6170                 :             :                 else
    6171                 :        8778 :                         varsourceline = 0;
    6172                 :       18306 :                 read_gucstate_binary(&srcptr, srcend,
    6173                 :             :                                                          &varsource, sizeof(varsource));
    6174                 :       18306 :                 read_gucstate_binary(&srcptr, srcend,
    6175                 :             :                                                          &varscontext, sizeof(varscontext));
    6176                 :       18306 :                 read_gucstate_binary(&srcptr, srcend,
    6177                 :             :                                                          &varsrole, sizeof(varsrole));
    6178                 :             : 
    6179                 :       18306 :                 error_context_name_and_value[0] = varname;
    6180                 :       18306 :                 error_context_name_and_value[1] = varvalue;
    6181                 :       18306 :                 error_context_callback.arg = &error_context_name_and_value[0];
    6182                 :       36612 :                 result = set_config_option_ext(varname, varvalue,
    6183                 :       18306 :                                                                            varscontext, varsource, varsrole,
    6184                 :             :                                                                            GUC_ACTION_SET, true, ERROR, true);
    6185         [ +  - ]:       18306 :                 if (result <= 0)
    6186   [ #  #  #  # ]:           0 :                         ereport(ERROR,
    6187                 :             :                                         (errcode(ERRCODE_INTERNAL_ERROR),
    6188                 :             :                                          errmsg("parameter \"%s\" could not be set", varname)));
    6189         [ +  + ]:       18306 :                 if (varsourcefile[0])
    6190                 :        9528 :                         set_config_sourcefile(varname, varsourcefile, varsourceline);
    6191                 :       18306 :                 error_context_callback.arg = NULL;
    6192                 :       18306 :         }
    6193                 :             : 
    6194                 :         477 :         error_context_stack = error_context_callback.previous;
    6195                 :         477 : }
    6196                 :             : 
    6197                 :             : /*
    6198                 :             :  * A little "long argument" simulation, although not quite GNU
    6199                 :             :  * compliant. Takes a string of the form "some-option=some value" and
    6200                 :             :  * returns name = "some_option" and value = "some value" in palloc'ed
    6201                 :             :  * storage. Note that '-' is converted to '_' in the option name. If
    6202                 :             :  * there is no '=' in the input string then value will be NULL.
    6203                 :             :  */
    6204                 :             : void
    6205                 :        4938 : ParseLongOption(const char *string, char **name, char **value)
    6206                 :             : {
    6207                 :        4938 :         size_t          equal_pos;
    6208                 :             : 
    6209         [ +  - ]:        4938 :         Assert(string);
    6210         [ +  - ]:        4938 :         Assert(name);
    6211         [ +  - ]:        4938 :         Assert(value);
    6212                 :             : 
    6213                 :        4938 :         equal_pos = strcspn(string, "=");
    6214                 :             : 
    6215         [ +  - ]:        4938 :         if (string[equal_pos] == '=')
    6216                 :             :         {
    6217                 :        4938 :                 *name = palloc(equal_pos + 1);
    6218                 :        4938 :                 strlcpy(*name, string, equal_pos + 1);
    6219                 :             : 
    6220                 :        4938 :                 *value = pstrdup(&string[equal_pos + 1]);
    6221                 :        4938 :         }
    6222                 :             :         else
    6223                 :             :         {
    6224                 :             :                 /* no equal sign in string */
    6225                 :           0 :                 *name = pstrdup(string);
    6226                 :           0 :                 *value = NULL;
    6227                 :             :         }
    6228                 :             : 
    6229         [ +  + ]:       65306 :         for (char *cp = *name; *cp; cp++)
    6230         [ +  + ]:       60369 :                 if (*cp == '-')
    6231                 :           1 :                         *cp = '_';
    6232                 :        4938 : }
    6233                 :             : 
    6234                 :             : 
    6235                 :             : /*
    6236                 :             :  * Transform array of GUC settings into lists of names and values. The lists
    6237                 :             :  * are faster to process in cases where the settings must be applied
    6238                 :             :  * repeatedly (e.g. for each function invocation).
    6239                 :             :  */
    6240                 :             : void
    6241                 :         789 : TransformGUCArray(ArrayType *array, List **names, List **values)
    6242                 :             : {
    6243         [ +  - ]:         789 :         Assert(array != NULL);
    6244         [ +  - ]:         789 :         Assert(ARR_ELEMTYPE(array) == TEXTOID);
    6245         [ +  - ]:         789 :         Assert(ARR_NDIM(array) == 1);
    6246         [ +  - ]:         789 :         Assert(ARR_LBOUND(array)[0] == 1);
    6247                 :             : 
    6248                 :         789 :         *names = NIL;
    6249                 :         789 :         *values = NIL;
    6250         [ +  + ]:        5418 :         for (int i = 1; i <= ARR_DIMS(array)[0]; i++)
    6251                 :             :         {
    6252                 :        4629 :                 Datum           d;
    6253                 :        4629 :                 bool            isnull;
    6254                 :        4629 :                 char       *s;
    6255                 :        4629 :                 char       *name;
    6256                 :        4629 :                 char       *value;
    6257                 :             : 
    6258                 :        4629 :                 d = array_ref(array, 1, &i,
    6259                 :             :                                           -1 /* varlenarray */ ,
    6260                 :             :                                           -1 /* TEXT's typlen */ ,
    6261                 :             :                                           false /* TEXT's typbyval */ ,
    6262                 :             :                                           TYPALIGN_INT /* TEXT's typalign */ ,
    6263                 :             :                                           &isnull);
    6264                 :             : 
    6265         [ -  + ]:        4629 :                 if (isnull)
    6266                 :           0 :                         continue;
    6267                 :             : 
    6268                 :        4629 :                 s = TextDatumGetCString(d);
    6269                 :             : 
    6270                 :        4629 :                 ParseLongOption(s, &name, &value);
    6271         [ +  - ]:        4629 :                 if (!value)
    6272                 :             :                 {
    6273   [ #  #  #  # ]:           0 :                         ereport(WARNING,
    6274                 :             :                                         (errcode(ERRCODE_SYNTAX_ERROR),
    6275                 :             :                                          errmsg("could not parse setting for parameter \"%s\"",
    6276                 :             :                                                         name)));
    6277                 :           0 :                         pfree(name);
    6278                 :           0 :                         continue;
    6279                 :             :                 }
    6280                 :             : 
    6281                 :        4629 :                 *names = lappend(*names, name);
    6282                 :        4629 :                 *values = lappend(*values, value);
    6283                 :             : 
    6284                 :        4629 :                 pfree(s);
    6285      [ -  -  + ]:        4629 :         }
    6286                 :         789 : }
    6287                 :             : 
    6288                 :             : 
    6289                 :             : /*
    6290                 :             :  * Handle options fetched from pg_db_role_setting.setconfig,
    6291                 :             :  * pg_proc.proconfig, etc.  Caller must specify proper context/source/action.
    6292                 :             :  *
    6293                 :             :  * The array parameter must be an array of TEXT (it must not be NULL).
    6294                 :             :  */
    6295                 :             : void
    6296                 :         775 : ProcessGUCArray(ArrayType *array,
    6297                 :             :                                 GucContext context, GucSource source, GucAction action)
    6298                 :             : {
    6299                 :         775 :         List       *gucNames;
    6300                 :         775 :         List       *gucValues;
    6301                 :         775 :         ListCell   *lc1;
    6302                 :         775 :         ListCell   *lc2;
    6303                 :             : 
    6304                 :         775 :         TransformGUCArray(array, &gucNames, &gucValues);
    6305   [ +  -  +  +  :        5392 :         forboth(lc1, gucNames, lc2, gucValues)
          +  -  +  +  +  
                +  +  + ]
    6306                 :             :         {
    6307                 :        4617 :                 char       *name = lfirst(lc1);
    6308                 :        4617 :                 char       *value = lfirst(lc2);
    6309                 :             : 
    6310                 :        9234 :                 (void) set_config_option(name, value,
    6311                 :        4617 :                                                                  context, source,
    6312                 :        4617 :                                                                  action, true, 0, false);
    6313                 :             : 
    6314                 :        4617 :                 pfree(name);
    6315                 :        4617 :                 pfree(value);
    6316                 :        4617 :         }
    6317                 :             : 
    6318                 :         775 :         list_free(gucNames);
    6319                 :         775 :         list_free(gucValues);
    6320                 :         775 : }
    6321                 :             : 
    6322                 :             : 
    6323                 :             : /*
    6324                 :             :  * Add an entry to an option array.  The array parameter may be NULL
    6325                 :             :  * to indicate the current table entry is NULL.
    6326                 :             :  */
    6327                 :             : ArrayType *
    6328                 :          30 : GUCArrayAdd(ArrayType *array, const char *name, const char *value)
    6329                 :             : {
    6330                 :          30 :         struct config_generic *record;
    6331                 :          30 :         Datum           datum;
    6332                 :          30 :         char       *newval;
    6333                 :          30 :         ArrayType  *a;
    6334                 :             : 
    6335         [ +  - ]:          30 :         Assert(name);
    6336         [ +  - ]:          30 :         Assert(value);
    6337                 :             : 
    6338                 :             :         /* test if the option is valid and we're allowed to set it */
    6339                 :          30 :         (void) validate_option_array_item(name, value, false);
    6340                 :             : 
    6341                 :             :         /* normalize name (converts obsolete GUC names to modern spellings) */
    6342                 :          30 :         record = find_option(name, false, true, WARNING);
    6343         [ -  + ]:          30 :         if (record)
    6344                 :          30 :                 name = record->name;
    6345                 :             : 
    6346                 :             :         /* build new item for array */
    6347                 :          30 :         newval = psprintf("%s=%s", name, value);
    6348                 :          30 :         datum = CStringGetTextDatum(newval);
    6349                 :             : 
    6350         [ +  + ]:          30 :         if (array)
    6351                 :             :         {
    6352                 :          16 :                 int                     index;
    6353                 :          16 :                 bool            isnull;
    6354                 :             : 
    6355         [ +  - ]:          16 :                 Assert(ARR_ELEMTYPE(array) == TEXTOID);
    6356         [ +  - ]:          16 :                 Assert(ARR_NDIM(array) == 1);
    6357         [ +  - ]:          16 :                 Assert(ARR_LBOUND(array)[0] == 1);
    6358                 :             : 
    6359                 :          16 :                 index = ARR_DIMS(array)[0] + 1; /* add after end */
    6360                 :             : 
    6361         [ +  + ]:          62 :                 for (int i = 1; i <= ARR_DIMS(array)[0]; i++)
    6362                 :             :                 {
    6363                 :          46 :                         Datum           d;
    6364                 :          46 :                         char       *current;
    6365                 :             : 
    6366                 :          46 :                         d = array_ref(array, 1, &i,
    6367                 :             :                                                   -1 /* varlenarray */ ,
    6368                 :             :                                                   -1 /* TEXT's typlen */ ,
    6369                 :             :                                                   false /* TEXT's typbyval */ ,
    6370                 :             :                                                   TYPALIGN_INT /* TEXT's typalign */ ,
    6371                 :             :                                                   &isnull);
    6372         [ -  + ]:          46 :                         if (isnull)
    6373                 :           0 :                                 continue;
    6374                 :          46 :                         current = TextDatumGetCString(d);
    6375                 :             : 
    6376                 :             :                         /* check for match up through and including '=' */
    6377         [ +  + ]:          46 :                         if (strncmp(current, newval, strlen(name) + 1) == 0)
    6378                 :             :                         {
    6379                 :           1 :                                 index = i;
    6380                 :           1 :                                 break;
    6381                 :             :                         }
    6382      [ -  +  + ]:          46 :                 }
    6383                 :             : 
    6384                 :          32 :                 a = array_set(array, 1, &index,
    6385                 :          16 :                                           datum,
    6386                 :             :                                           false,
    6387                 :             :                                           -1 /* varlena array */ ,
    6388                 :             :                                           -1 /* TEXT's typlen */ ,
    6389                 :             :                                           false /* TEXT's typbyval */ ,
    6390                 :             :                                           TYPALIGN_INT /* TEXT's typalign */ );
    6391                 :          16 :         }
    6392                 :             :         else
    6393                 :          14 :                 a = construct_array_builtin(&datum, 1, TEXTOID);
    6394                 :             : 
    6395                 :          60 :         return a;
    6396                 :          30 : }
    6397                 :             : 
    6398                 :             : 
    6399                 :             : /*
    6400                 :             :  * Delete an entry from an option array.  The array parameter may be NULL
    6401                 :             :  * to indicate the current table entry is NULL.  Also, if the return value
    6402                 :             :  * is NULL then a null should be stored.
    6403                 :             :  */
    6404                 :             : ArrayType *
    6405                 :           0 : GUCArrayDelete(ArrayType *array, const char *name)
    6406                 :             : {
    6407                 :           0 :         struct config_generic *record;
    6408                 :           0 :         ArrayType  *newarray;
    6409                 :           0 :         int                     index;
    6410                 :             : 
    6411         [ #  # ]:           0 :         Assert(name);
    6412                 :             : 
    6413                 :             :         /* test if the option is valid and we're allowed to set it */
    6414                 :           0 :         (void) validate_option_array_item(name, NULL, false);
    6415                 :             : 
    6416                 :             :         /* normalize name (converts obsolete GUC names to modern spellings) */
    6417                 :           0 :         record = find_option(name, false, true, WARNING);
    6418         [ #  # ]:           0 :         if (record)
    6419                 :           0 :                 name = record->name;
    6420                 :             : 
    6421                 :             :         /* if array is currently null, then surely nothing to delete */
    6422         [ #  # ]:           0 :         if (!array)
    6423                 :           0 :                 return NULL;
    6424                 :             : 
    6425                 :           0 :         newarray = NULL;
    6426                 :           0 :         index = 1;
    6427                 :             : 
    6428         [ #  # ]:           0 :         for (int i = 1; i <= ARR_DIMS(array)[0]; i++)
    6429                 :             :         {
    6430                 :           0 :                 Datum           d;
    6431                 :           0 :                 char       *val;
    6432                 :           0 :                 bool            isnull;
    6433                 :             : 
    6434                 :           0 :                 d = array_ref(array, 1, &i,
    6435                 :             :                                           -1 /* varlenarray */ ,
    6436                 :             :                                           -1 /* TEXT's typlen */ ,
    6437                 :             :                                           false /* TEXT's typbyval */ ,
    6438                 :             :                                           TYPALIGN_INT /* TEXT's typalign */ ,
    6439                 :             :                                           &isnull);
    6440         [ #  # ]:           0 :                 if (isnull)
    6441                 :           0 :                         continue;
    6442                 :           0 :                 val = TextDatumGetCString(d);
    6443                 :             : 
    6444                 :             :                 /* ignore entry if it's what we want to delete */
    6445                 :           0 :                 if (strncmp(val, name, strlen(name)) == 0
    6446   [ #  #  #  # ]:           0 :                         && val[strlen(name)] == '=')
    6447                 :           0 :                         continue;
    6448                 :             : 
    6449                 :             :                 /* else add it to the output array */
    6450         [ #  # ]:           0 :                 if (newarray)
    6451                 :           0 :                         newarray = array_set(newarray, 1, &index,
    6452                 :           0 :                                                                  d,
    6453                 :             :                                                                  false,
    6454                 :             :                                                                  -1 /* varlenarray */ ,
    6455                 :             :                                                                  -1 /* TEXT's typlen */ ,
    6456                 :             :                                                                  false /* TEXT's typbyval */ ,
    6457                 :             :                                                                  TYPALIGN_INT /* TEXT's typalign */ );
    6458                 :             :                 else
    6459                 :           0 :                         newarray = construct_array_builtin(&d, 1, TEXTOID);
    6460                 :             : 
    6461                 :           0 :                 index++;
    6462      [ #  #  # ]:           0 :         }
    6463                 :             : 
    6464                 :           0 :         return newarray;
    6465                 :           0 : }
    6466                 :             : 
    6467                 :             : 
    6468                 :             : /*
    6469                 :             :  * Given a GUC array, delete all settings from it that our permission
    6470                 :             :  * level allows: if superuser, delete them all; if regular user, only
    6471                 :             :  * those that are PGC_USERSET or we have permission to set
    6472                 :             :  */
    6473                 :             : ArrayType *
    6474                 :           0 : GUCArrayReset(ArrayType *array)
    6475                 :             : {
    6476                 :           0 :         ArrayType  *newarray;
    6477                 :           0 :         int                     index;
    6478                 :             : 
    6479                 :             :         /* if array is currently null, nothing to do */
    6480         [ #  # ]:           0 :         if (!array)
    6481                 :           0 :                 return NULL;
    6482                 :             : 
    6483                 :             :         /* if we're superuser, we can delete everything, so just do it */
    6484         [ #  # ]:           0 :         if (superuser())
    6485                 :           0 :                 return NULL;
    6486                 :             : 
    6487                 :           0 :         newarray = NULL;
    6488                 :           0 :         index = 1;
    6489                 :             : 
    6490         [ #  # ]:           0 :         for (int i = 1; i <= ARR_DIMS(array)[0]; i++)
    6491                 :             :         {
    6492                 :           0 :                 Datum           d;
    6493                 :           0 :                 char       *val;
    6494                 :           0 :                 char       *eqsgn;
    6495                 :           0 :                 bool            isnull;
    6496                 :             : 
    6497                 :           0 :                 d = array_ref(array, 1, &i,
    6498                 :             :                                           -1 /* varlenarray */ ,
    6499                 :             :                                           -1 /* TEXT's typlen */ ,
    6500                 :             :                                           false /* TEXT's typbyval */ ,
    6501                 :             :                                           TYPALIGN_INT /* TEXT's typalign */ ,
    6502                 :             :                                           &isnull);
    6503         [ #  # ]:           0 :                 if (isnull)
    6504                 :           0 :                         continue;
    6505                 :           0 :                 val = TextDatumGetCString(d);
    6506                 :             : 
    6507                 :           0 :                 eqsgn = strchr(val, '=');
    6508                 :           0 :                 *eqsgn = '\0';
    6509                 :             : 
    6510                 :             :                 /* skip if we have permission to delete it */
    6511         [ #  # ]:           0 :                 if (validate_option_array_item(val, NULL, true))
    6512                 :           0 :                         continue;
    6513                 :             : 
    6514                 :             :                 /* else add it to the output array */
    6515         [ #  # ]:           0 :                 if (newarray)
    6516                 :           0 :                         newarray = array_set(newarray, 1, &index,
    6517                 :           0 :                                                                  d,
    6518                 :             :                                                                  false,
    6519                 :             :                                                                  -1 /* varlenarray */ ,
    6520                 :             :                                                                  -1 /* TEXT's typlen */ ,
    6521                 :             :                                                                  false /* TEXT's typbyval */ ,
    6522                 :             :                                                                  TYPALIGN_INT /* TEXT's typalign */ );
    6523                 :             :                 else
    6524                 :           0 :                         newarray = construct_array_builtin(&d, 1, TEXTOID);
    6525                 :             : 
    6526                 :           0 :                 index++;
    6527                 :           0 :                 pfree(val);
    6528      [ #  #  # ]:           0 :         }
    6529                 :             : 
    6530                 :           0 :         return newarray;
    6531                 :           0 : }
    6532                 :             : 
    6533                 :             : /*
    6534                 :             :  * Validate a proposed option setting for GUCArrayAdd/Delete/Reset.
    6535                 :             :  *
    6536                 :             :  * name is the option name.  value is the proposed value for the Add case,
    6537                 :             :  * or NULL for the Delete/Reset cases.  If skipIfNoPermissions is true, it's
    6538                 :             :  * not an error to have no permissions to set the option.
    6539                 :             :  *
    6540                 :             :  * Returns true if OK, false if skipIfNoPermissions is true and user does not
    6541                 :             :  * have permission to change this option (all other error cases result in an
    6542                 :             :  * error being thrown).
    6543                 :             :  */
    6544                 :             : static bool
    6545                 :          30 : validate_option_array_item(const char *name, const char *value,
    6546                 :             :                                                    bool skipIfNoPermissions)
    6547                 :             : 
    6548                 :             : {
    6549                 :          30 :         struct config_generic *gconf;
    6550                 :          30 :         bool            reset_custom;
    6551                 :             : 
    6552                 :             :         /*
    6553                 :             :          * There are three cases to consider:
    6554                 :             :          *
    6555                 :             :          * name is a known GUC variable.  Check the value normally, check
    6556                 :             :          * permissions normally (i.e., allow if variable is USERSET, or if it's
    6557                 :             :          * SUSET and user is superuser or holds ACL_SET permissions).
    6558                 :             :          *
    6559                 :             :          * name is not known, but exists or can be created as a placeholder (i.e.,
    6560                 :             :          * it has a valid custom name).  We allow this case if you're a superuser,
    6561                 :             :          * otherwise not.  Superusers are assumed to know what they're doing. We
    6562                 :             :          * can't allow it for other users, because when the placeholder is
    6563                 :             :          * resolved it might turn out to be a SUSET variable.  (With currently
    6564                 :             :          * available infrastructure, we can actually handle such cases within the
    6565                 :             :          * current session --- but once an entry is made in pg_db_role_setting,
    6566                 :             :          * it's assumed to be fully validated.)
    6567                 :             :          *
    6568                 :             :          * name is not known and can't be created as a placeholder.  Throw error,
    6569                 :             :          * unless skipIfNoPermissions or reset_custom is true.  If reset_custom is
    6570                 :             :          * true, this is a RESET or RESET ALL operation for an unknown custom GUC
    6571                 :             :          * with a reserved prefix, in which case we want to fall through to the
    6572                 :             :          * placeholder case described in the preceding paragraph (else there'd be
    6573                 :             :          * no way for users to remove them).  Otherwise, return false.
    6574                 :             :          */
    6575         [ +  - ]:          30 :         reset_custom = (!value && valid_custom_variable_name(name));
    6576         [ -  + ]:          30 :         gconf = find_option(name, true, skipIfNoPermissions || reset_custom, ERROR);
    6577   [ -  +  #  # ]:          30 :         if (!gconf && !reset_custom)
    6578                 :             :         {
    6579                 :             :                 /* not known, failed to make a placeholder */
    6580                 :           0 :                 return false;
    6581                 :             :         }
    6582                 :             : 
    6583   [ +  -  -  + ]:          30 :         if (!gconf || gconf->flags & GUC_CUSTOM_PLACEHOLDER)
    6584                 :             :         {
    6585                 :             :                 /*
    6586                 :             :                  * We cannot do any meaningful check on the value, so only permissions
    6587                 :             :                  * are useful to check.
    6588                 :             :                  */
    6589   [ #  #  #  # ]:           0 :                 if (superuser() ||
    6590                 :           0 :                         pg_parameter_aclcheck(name, GetUserId(), ACL_SET) == ACLCHECK_OK)
    6591                 :           0 :                         return true;
    6592         [ #  # ]:           0 :                 if (skipIfNoPermissions)
    6593                 :           0 :                         return false;
    6594   [ #  #  #  # ]:           0 :                 ereport(ERROR,
    6595                 :             :                                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
    6596                 :             :                                  errmsg("permission denied to set parameter \"%s\"", name)));
    6597                 :           0 :         }
    6598                 :             : 
    6599                 :             :         /* manual permissions check so we can avoid an error being thrown */
    6600         [ +  + ]:          30 :         if (gconf->context == PGC_USERSET)
    6601                 :             :                  /* ok */ ;
    6602   [ +  -  #  # ]:           4 :         else if (gconf->context == PGC_SUSET &&
    6603         [ -  + ]:           2 :                          (superuser() ||
    6604                 :           0 :                           pg_parameter_aclcheck(name, GetUserId(), ACL_SET) == ACLCHECK_OK))
    6605                 :             :                  /* ok */ ;
    6606         [ #  # ]:           0 :         else if (skipIfNoPermissions)
    6607                 :           0 :                 return false;
    6608                 :             :         /* if a permissions error should be thrown, let set_config_option do it */
    6609                 :             : 
    6610                 :             :         /* test for permissions and valid option value */
    6611                 :          60 :         (void) set_config_option(name, value,
    6612                 :          30 :                                                          superuser() ? PGC_SUSET : PGC_USERSET,
    6613                 :             :                                                          PGC_S_TEST, GUC_ACTION_SET, false, 0, false);
    6614                 :             : 
    6615                 :          30 :         return true;
    6616                 :          30 : }
    6617                 :             : 
    6618                 :             : 
    6619                 :             : /*
    6620                 :             :  * Called by check_hooks that want to override the normal
    6621                 :             :  * ERRCODE_INVALID_PARAMETER_VALUE SQLSTATE for check hook failures.
    6622                 :             :  *
    6623                 :             :  * Note that GUC_check_errmsg() etc are just macros that result in a direct
    6624                 :             :  * assignment to the associated variables.  That is ugly, but forced by the
    6625                 :             :  * limitations of C's macro mechanisms.
    6626                 :             :  */
    6627                 :             : void
    6628                 :           7 : GUC_check_errcode(int sqlerrcode)
    6629                 :             : {
    6630                 :           7 :         GUC_check_errcode_value = sqlerrcode;
    6631                 :           7 : }
    6632                 :             : 
    6633                 :             : 
    6634                 :             : /*
    6635                 :             :  * Convenience functions to manage calling a variable's check_hook.
    6636                 :             :  * These mostly take care of the protocol for letting check hooks supply
    6637                 :             :  * portions of the error report on failure.
    6638                 :             :  */
    6639                 :             : 
    6640                 :             : static bool
    6641                 :       15915 : call_bool_check_hook(const struct config_generic *conf, bool *newval, void **extra,
    6642                 :             :                                          GucSource source, int elevel)
    6643                 :             : {
    6644                 :             :         /* Quick success if no hook */
    6645         [ +  + ]:       15915 :         if (!conf->_bool.check_hook)
    6646                 :       13881 :                 return true;
    6647                 :             : 
    6648                 :             :         /* Reset variables that might be set by hook */
    6649                 :        2034 :         GUC_check_errcode_value = ERRCODE_INVALID_PARAMETER_VALUE;
    6650                 :        2034 :         GUC_check_errmsg_string = NULL;
    6651                 :        2034 :         GUC_check_errdetail_string = NULL;
    6652                 :        2034 :         GUC_check_errhint_string = NULL;
    6653                 :             : 
    6654         [ +  + ]:        2034 :         if (!conf->_bool.check_hook(newval, extra, source))
    6655                 :             :         {
    6656   [ -  +  #  #  :          10 :                 ereport(elevel,
          +  +  +  -  -  
          +  -  +  #  #  
                   #  # ]
    6657                 :             :                                 (errcode(GUC_check_errcode_value),
    6658                 :             :                                  GUC_check_errmsg_string ?
    6659                 :             :                                  errmsg_internal("%s", GUC_check_errmsg_string) :
    6660                 :             :                                  errmsg("invalid value for parameter \"%s\": %d",
    6661                 :             :                                                 conf->name, (int) *newval),
    6662                 :             :                                  GUC_check_errdetail_string ?
    6663                 :             :                                  errdetail_internal("%s", GUC_check_errdetail_string) : 0,
    6664                 :             :                                  GUC_check_errhint_string ?
    6665                 :             :                                  errhint("%s", GUC_check_errhint_string) : 0));
    6666                 :             :                 /* Flush strings created in ErrorContext (ereport might not have) */
    6667                 :           0 :                 FlushErrorState();
    6668                 :           0 :                 return false;
    6669                 :             :         }
    6670                 :             : 
    6671                 :        2024 :         return true;
    6672                 :       15905 : }
    6673                 :             : 
    6674                 :             : static bool
    6675                 :        7298 : call_int_check_hook(const struct config_generic *conf, int *newval, void **extra,
    6676                 :             :                                         GucSource source, int elevel)
    6677                 :             : {
    6678                 :             :         /* Quick success if no hook */
    6679         [ +  + ]:        7298 :         if (!conf->_int.check_hook)
    6680                 :        6203 :                 return true;
    6681                 :             : 
    6682                 :             :         /* Reset variables that might be set by hook */
    6683                 :        1095 :         GUC_check_errcode_value = ERRCODE_INVALID_PARAMETER_VALUE;
    6684                 :        1095 :         GUC_check_errmsg_string = NULL;
    6685                 :        1095 :         GUC_check_errdetail_string = NULL;
    6686                 :        1095 :         GUC_check_errhint_string = NULL;
    6687                 :             : 
    6688         [ +  - ]:        1095 :         if (!conf->_int.check_hook(newval, extra, source))
    6689                 :             :         {
    6690   [ #  #  #  #  :           0 :                 ereport(elevel,
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
    6691                 :             :                                 (errcode(GUC_check_errcode_value),
    6692                 :             :                                  GUC_check_errmsg_string ?
    6693                 :             :                                  errmsg_internal("%s", GUC_check_errmsg_string) :
    6694                 :             :                                  errmsg("invalid value for parameter \"%s\": %d",
    6695                 :             :                                                 conf->name, *newval),
    6696                 :             :                                  GUC_check_errdetail_string ?
    6697                 :             :                                  errdetail_internal("%s", GUC_check_errdetail_string) : 0,
    6698                 :             :                                  GUC_check_errhint_string ?
    6699                 :             :                                  errhint("%s", GUC_check_errhint_string) : 0));
    6700                 :             :                 /* Flush strings created in ErrorContext (ereport might not have) */
    6701                 :           0 :                 FlushErrorState();
    6702                 :           0 :                 return false;
    6703                 :             :         }
    6704                 :             : 
    6705                 :        1095 :         return true;
    6706                 :        7298 : }
    6707                 :             : 
    6708                 :             : static bool
    6709                 :        1484 : call_real_check_hook(const struct config_generic *conf, double *newval, void **extra,
    6710                 :             :                                          GucSource source, int elevel)
    6711                 :             : {
    6712                 :             :         /* Quick success if no hook */
    6713         [ +  + ]:        1484 :         if (!conf->_real.check_hook)
    6714                 :        1478 :                 return true;
    6715                 :             : 
    6716                 :             :         /* Reset variables that might be set by hook */
    6717                 :           6 :         GUC_check_errcode_value = ERRCODE_INVALID_PARAMETER_VALUE;
    6718                 :           6 :         GUC_check_errmsg_string = NULL;
    6719                 :           6 :         GUC_check_errdetail_string = NULL;
    6720                 :           6 :         GUC_check_errhint_string = NULL;
    6721                 :             : 
    6722         [ +  - ]:           6 :         if (!conf->_real.check_hook(newval, extra, source))
    6723                 :             :         {
    6724   [ #  #  #  #  :           0 :                 ereport(elevel,
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
    6725                 :             :                                 (errcode(GUC_check_errcode_value),
    6726                 :             :                                  GUC_check_errmsg_string ?
    6727                 :             :                                  errmsg_internal("%s", GUC_check_errmsg_string) :
    6728                 :             :                                  errmsg("invalid value for parameter \"%s\": %g",
    6729                 :             :                                                 conf->name, *newval),
    6730                 :             :                                  GUC_check_errdetail_string ?
    6731                 :             :                                  errdetail_internal("%s", GUC_check_errdetail_string) : 0,
    6732                 :             :                                  GUC_check_errhint_string ?
    6733                 :             :                                  errhint("%s", GUC_check_errhint_string) : 0));
    6734                 :             :                 /* Flush strings created in ErrorContext (ereport might not have) */
    6735                 :           0 :                 FlushErrorState();
    6736                 :           0 :                 return false;
    6737                 :             :         }
    6738                 :             : 
    6739                 :           6 :         return true;
    6740                 :        1484 : }
    6741                 :             : 
    6742                 :             : static bool
    6743                 :       36255 : call_string_check_hook(const struct config_generic *conf, char **newval, void **extra,
    6744                 :             :                                            GucSource source, int elevel)
    6745                 :             : {
    6746                 :       36255 :         volatile bool result = true;
    6747                 :             : 
    6748                 :             :         /* Quick success if no hook */
    6749         [ +  + ]:       36255 :         if (!conf->_string.check_hook)
    6750                 :        2034 :                 return true;
    6751                 :             : 
    6752                 :             :         /*
    6753                 :             :          * If elevel is ERROR, or if the check_hook itself throws an elog
    6754                 :             :          * (undesirable, but not always avoidable), make sure we don't leak the
    6755                 :             :          * already-malloc'd newval string.
    6756                 :             :          */
    6757         [ +  + ]:       34221 :         PG_TRY();
    6758                 :             :         {
    6759                 :             :                 /* Reset variables that might be set by hook */
    6760                 :       34197 :                 GUC_check_errcode_value = ERRCODE_INVALID_PARAMETER_VALUE;
    6761                 :       34197 :                 GUC_check_errmsg_string = NULL;
    6762                 :       34197 :                 GUC_check_errdetail_string = NULL;
    6763                 :       34197 :                 GUC_check_errhint_string = NULL;
    6764                 :             : 
    6765         [ +  + ]:       34197 :                 if (!conf->_string.check_hook(newval, extra, source))
    6766                 :             :                 {
    6767   [ -  +  #  #  :          46 :                         ereport(elevel,
          +  +  +  +  +  
          -  +  +  -  +  
             #  #  #  # ]
    6768                 :             :                                         (errcode(GUC_check_errcode_value),
    6769                 :             :                                          GUC_check_errmsg_string ?
    6770                 :             :                                          errmsg_internal("%s", GUC_check_errmsg_string) :
    6771                 :             :                                          errmsg("invalid value for parameter \"%s\": \"%s\"",
    6772                 :             :                                                         conf->name, *newval ? *newval : ""),
    6773                 :             :                                          GUC_check_errdetail_string ?
    6774                 :             :                                          errdetail_internal("%s", GUC_check_errdetail_string) : 0,
    6775                 :             :                                          GUC_check_errhint_string ?
    6776                 :             :                                          errhint("%s", GUC_check_errhint_string) : 0));
    6777                 :             :                         /* Flush strings created in ErrorContext (ereport might not have) */
    6778                 :           0 :                         FlushErrorState();
    6779                 :           0 :                         result = false;
    6780                 :           0 :                 }
    6781                 :             :         }
    6782                 :       34175 :         PG_CATCH();
    6783                 :             :         {
    6784                 :          24 :                 guc_free(*newval);
    6785                 :          24 :                 PG_RE_THROW();
    6786                 :             :         }
    6787         [ +  - ]:       34151 :         PG_END_TRY();
    6788                 :             : 
    6789                 :       34151 :         return result;
    6790                 :       36185 : }
    6791                 :             : 
    6792                 :             : static bool
    6793                 :        5400 : call_enum_check_hook(const struct config_generic *conf, int *newval, void **extra,
    6794                 :             :                                          GucSource source, int elevel)
    6795                 :             : {
    6796                 :             :         /* Quick success if no hook */
    6797         [ +  + ]:        5400 :         if (!conf->_enum.check_hook)
    6798                 :        4397 :                 return true;
    6799                 :             : 
    6800                 :             :         /* Reset variables that might be set by hook */
    6801                 :        1003 :         GUC_check_errcode_value = ERRCODE_INVALID_PARAMETER_VALUE;
    6802                 :        1003 :         GUC_check_errmsg_string = NULL;
    6803                 :        1003 :         GUC_check_errdetail_string = NULL;
    6804                 :        1003 :         GUC_check_errhint_string = NULL;
    6805                 :             : 
    6806         [ +  - ]:        1003 :         if (!conf->_enum.check_hook(newval, extra, source))
    6807                 :             :         {
    6808   [ #  #  #  #  :           0 :                 ereport(elevel,
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
    6809                 :             :                                 (errcode(GUC_check_errcode_value),
    6810                 :             :                                  GUC_check_errmsg_string ?
    6811                 :             :                                  errmsg_internal("%s", GUC_check_errmsg_string) :
    6812                 :             :                                  errmsg("invalid value for parameter \"%s\": \"%s\"",
    6813                 :             :                                                 conf->name,
    6814                 :             :                                                 config_enum_lookup_by_value(conf, *newval)),
    6815                 :             :                                  GUC_check_errdetail_string ?
    6816                 :             :                                  errdetail_internal("%s", GUC_check_errdetail_string) : 0,
    6817                 :             :                                  GUC_check_errhint_string ?
    6818                 :             :                                  errhint("%s", GUC_check_errhint_string) : 0));
    6819                 :             :                 /* Flush strings created in ErrorContext (ereport might not have) */
    6820                 :           0 :                 FlushErrorState();
    6821                 :           0 :                 return false;
    6822                 :             :         }
    6823                 :             : 
    6824                 :        1003 :         return true;
    6825                 :        5400 : }
        

Generated by: LCOV version 2.3.2-1