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

Generated by: LCOV version 1.14