LCOV - code coverage report
Current view: top level - src/backend/utils/misc - guc.c (source / functions) Hit Total Coverage
Test: PostgreSQL 19devel Lines: 1883 2265 83.1 %
Date: 2025-10-23 17:17:24 Functions: 96 99 97.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.16