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

Generated by: LCOV version 1.14