LCOV - differential code coverage report
Current view: top level - src/backend/commands - variable.c (source / functions) Coverage Total Hit UNC LBC UIC UBC GBC GIC GNC CBC EUB ECB DUB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 67.6 % 420 284 97 22 65 35 20 137 75 52 62 140 3 3
Current Date: 2023-04-08 15:15:32 Functions: 94.4 % 36 34 2 18 16 2 33 1
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

           TLA  Line data    Source code
       1                 : /*-------------------------------------------------------------------------
       2                 :  *
       3                 :  * variable.c
       4                 :  *      Routines for handling specialized SET variables.
       5                 :  *
       6                 :  *
       7                 :  * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
       8                 :  * Portions Copyright (c) 1994, Regents of the University of California
       9                 :  *
      10                 :  *
      11                 :  * IDENTIFICATION
      12                 :  *    src/backend/commands/variable.c
      13                 :  *
      14                 :  *-------------------------------------------------------------------------
      15                 :  */
      16                 : 
      17                 : #include "postgres.h"
      18                 : 
      19                 : #include <ctype.h>
      20                 : 
      21                 : #include "access/htup_details.h"
      22                 : #include "access/parallel.h"
      23                 : #include "access/xact.h"
      24                 : #include "access/xlog.h"
      25                 : #include "access/xlogprefetcher.h"
      26                 : #include "catalog/pg_authid.h"
      27                 : #include "common/string.h"
      28                 : #include "mb/pg_wchar.h"
      29                 : #include "miscadmin.h"
      30                 : #include "postmaster/postmaster.h"
      31                 : #include "postmaster/syslogger.h"
      32                 : #include "storage/bufmgr.h"
      33                 : #include "utils/acl.h"
      34                 : #include "utils/backend_status.h"
      35                 : #include "utils/builtins.h"
      36                 : #include "utils/datetime.h"
      37                 : #include "utils/guc_hooks.h"
      38                 : #include "utils/snapmgr.h"
      39                 : #include "utils/syscache.h"
      40                 : #include "utils/timestamp.h"
      41                 : #include "utils/tzparser.h"
      42                 : #include "utils/varlena.h"
      43                 : 
      44                 : /*
      45                 :  * DATESTYLE
      46                 :  */
      47                 : 
      48                 : /*
      49                 :  * check_datestyle: GUC check_hook for datestyle
      50                 :  */
      51                 : bool
      52 GIC       12373 : check_datestyle(char **newval, void **extra, GucSource source)
      53                 : {
      54           12373 :     int         newDateStyle = DateStyle;
      55           12373 :     int         newDateOrder = DateOrder;
      56           12373 :     bool        have_style = false;
      57           12373 :     bool        have_order = false;
      58           12373 :     bool        ok = true;
      59                 :     char       *rawstring;
      60 ECB             :     int        *myextra;
      61                 :     char       *result;
      62                 :     List       *elemlist;
      63                 :     ListCell   *l;
      64                 : 
      65                 :     /* Need a modifiable copy of string */
      66 CBC       12373 :     rawstring = pstrdup(*newval);
      67                 : 
      68                 :     /* Parse string into list of identifiers */
      69 GIC       12373 :     if (!SplitIdentifierString(rawstring, ',', &elemlist))
      70                 :     {
      71                 :         /* syntax error in list */
      72 UIC           0 :         GUC_check_errdetail("List syntax is invalid.");
      73               0 :         pfree(rawstring);
      74 LBC           0 :         list_free(elemlist);
      75 UIC           0 :         return false;
      76                 :     }
      77 ECB             : 
      78 GIC       33130 :     foreach(l, elemlist)
      79                 :     {
      80 GBC       20757 :         char       *tok = (char *) lfirst(l);
      81 EUB             : 
      82                 :         /* Ugh. Somebody ought to write a table driven version -- mjl */
      83                 : 
      84 GIC       20757 :         if (pg_strcasecmp(tok, "ISO") == 0)
      85                 :         {
      86 CBC        8700 :             if (have_style && newDateStyle != USE_ISO_DATES)
      87 UIC           0 :                 ok = false;     /* conflicting styles */
      88 CBC        8700 :             newDateStyle = USE_ISO_DATES;
      89 GIC        8700 :             have_style = true;
      90                 :         }
      91           12057 :         else if (pg_strcasecmp(tok, "SQL") == 0)
      92 ECB             :         {
      93 GIC          15 :             if (have_style && newDateStyle != USE_SQL_DATES)
      94 LBC           0 :                 ok = false;     /* conflicting styles */
      95 GBC          15 :             newDateStyle = USE_SQL_DATES;
      96 CBC          15 :             have_style = true;
      97 ECB             :         }
      98 GIC       12042 :         else if (pg_strncasecmp(tok, "POSTGRES", 8) == 0)
      99 ECB             :         {
     100 GIC        3615 :             if (have_style && newDateStyle != USE_POSTGRES_DATES)
     101 LBC           0 :                 ok = false;     /* conflicting styles */
     102 GBC        3615 :             newDateStyle = USE_POSTGRES_DATES;
     103 CBC        3615 :             have_style = true;
     104 ECB             :         }
     105 GIC        8427 :         else if (pg_strcasecmp(tok, "GERMAN") == 0)
     106 ECB             :         {
     107 GIC          20 :             if (have_style && newDateStyle != USE_GERMAN_DATES)
     108 LBC           0 :                 ok = false;     /* conflicting styles */
     109 GBC          20 :             newDateStyle = USE_GERMAN_DATES;
     110 CBC          20 :             have_style = true;
     111 ECB             :             /* GERMAN also sets DMY, unless explicitly overridden */
     112 GIC          20 :             if (!have_order)
     113 CBC          20 :                 newDateOrder = DATEORDER_DMY;
     114                 :         }
     115            8407 :         else if (pg_strcasecmp(tok, "YMD") == 0)
     116 EUB             :         {
     117 CBC          18 :             if (have_order && newDateOrder != DATEORDER_YMD)
     118 LBC           0 :                 ok = false;     /* conflicting orders */
     119 GIC          18 :             newDateOrder = DATEORDER_YMD;
     120 CBC          18 :             have_order = true;
     121 ECB             :         }
     122 GIC       16755 :         else if (pg_strcasecmp(tok, "DMY") == 0 ||
     123 CBC        8366 :                  pg_strncasecmp(tok, "EURO", 4) == 0)
     124                 :         {
     125              32 :             if (have_order && newDateOrder != DATEORDER_DMY)
     126 UBC           0 :                 ok = false;     /* conflicting orders */
     127 CBC          32 :             newDateOrder = DATEORDER_DMY;
     128              32 :             have_order = true;
     129                 :         }
     130            8366 :         else if (pg_strcasecmp(tok, "MDY") == 0 ||
     131               9 :                  pg_strcasecmp(tok, "US") == 0 ||
     132 UIC           0 :                  pg_strncasecmp(tok, "NONEURO", 7) == 0)
     133 ECB             :         {
     134 GBC        8357 :             if (have_order && newDateOrder != DATEORDER_MDY)
     135 LBC           0 :                 ok = false;     /* conflicting orders */
     136 CBC        8357 :             newDateOrder = DATEORDER_MDY;
     137 GIC        8357 :             have_order = true;
     138 ECB             :         }
     139 LBC           0 :         else if (pg_strcasecmp(tok, "DEFAULT") == 0)
     140 EUB             :         {
     141                 :             /*
     142 ECB             :              * Easiest way to get the current DEFAULT state is to fetch the
     143 EUB             :              * DEFAULT string from guc.c and recursively parse it.
     144 ECB             :              *
     145                 :              * We can't simply "return check_datestyle(...)" because we need
     146                 :              * to handle constructs like "DEFAULT, ISO".
     147 EUB             :              */
     148                 :             char       *subval;
     149 UIC           0 :             void       *subextra = NULL;
     150                 : 
     151 UNC           0 :             subval = guc_strdup(LOG, GetConfigOptionResetString("datestyle"));
     152 UIC           0 :             if (!subval)
     153                 :             {
     154               0 :                 ok = false;
     155               0 :                 break;
     156                 :             }
     157 UBC           0 :             if (!check_datestyle(&subval, &subextra, source))
     158                 :             {
     159 UNC           0 :                 guc_free(subval);
     160 UBC           0 :                 ok = false;
     161 UIC           0 :                 break;
     162 EUB             :             }
     163 UBC           0 :             myextra = (int *) subextra;
     164 UIC           0 :             if (!have_style)
     165 UBC           0 :                 newDateStyle = myextra[0];
     166 UIC           0 :             if (!have_order)
     167 UBC           0 :                 newDateOrder = myextra[1];
     168 UNC           0 :             guc_free(subval);
     169               0 :             guc_free(subextra);
     170                 :         }
     171 EUB             :         else
     172                 :         {
     173 UBC           0 :             GUC_check_errdetail("Unrecognized key word: \"%s\".", tok);
     174               0 :             pfree(rawstring);
     175               0 :             list_free(elemlist);
     176               0 :             return false;
     177 EUB             :         }
     178                 :     }
     179                 : 
     180 GIC       12373 :     pfree(rawstring);
     181 GBC       12373 :     list_free(elemlist);
     182 EUB             : 
     183 GBC       12373 :     if (!ok)
     184 EUB             :     {
     185 UIC           0 :         GUC_check_errdetail("Conflicting \"datestyle\" specifications.");
     186               0 :         return false;
     187                 :     }
     188 ECB             : 
     189                 :     /*
     190                 :      * Prepare the canonical string to return.  GUC wants it guc_malloc'd.
     191                 :      */
     192 GNC       12373 :     result = (char *) guc_malloc(LOG, 32);
     193 GBC       12373 :     if (!result)
     194 UBC           0 :         return false;
     195                 : 
     196 GIC       12373 :     switch (newDateStyle)
     197                 :     {
     198            8712 :         case USE_ISO_DATES:
     199            8712 :             strcpy(result, "ISO");
     200 CBC        8712 :             break;
     201              15 :         case USE_SQL_DATES:
     202 GBC          15 :             strcpy(result, "SQL");
     203 GIC          15 :             break;
     204 CBC          20 :         case USE_GERMAN_DATES:
     205 GIC          20 :             strcpy(result, "German");
     206 CBC          20 :             break;
     207            3626 :         default:
     208            3626 :             strcpy(result, "Postgres");
     209            3626 :             break;
     210 ECB             :     }
     211 CBC       12373 :     switch (newDateOrder)
     212 ECB             :     {
     213 CBC          24 :         case DATEORDER_YMD:
     214              24 :             strcat(result, ", YMD");
     215              24 :             break;
     216              42 :         case DATEORDER_DMY:
     217              42 :             strcat(result, ", DMY");
     218 GIC          42 :             break;
     219 CBC       12307 :         default:
     220 GIC       12307 :             strcat(result, ", MDY");
     221 CBC       12307 :             break;
     222 ECB             :     }
     223                 : 
     224 GNC       12373 :     guc_free(*newval);
     225 CBC       12373 :     *newval = result;
     226 ECB             : 
     227                 :     /*
     228                 :      * Set up the "extra" struct actually used by assign_datestyle.
     229                 :      */
     230 GNC       12373 :     myextra = (int *) guc_malloc(LOG, 2 * sizeof(int));
     231 GIC       12373 :     if (!myextra)
     232 LBC           0 :         return false;
     233 CBC       12373 :     myextra[0] = newDateStyle;
     234 GIC       12373 :     myextra[1] = newDateOrder;
     235           12373 :     *extra = (void *) myextra;
     236                 : 
     237           12373 :     return true;
     238 ECB             : }
     239                 : 
     240 EUB             : /*
     241 ECB             :  * assign_datestyle: GUC assign_hook for datestyle
     242                 :  */
     243                 : void
     244 GIC       15715 : assign_datestyle(const char *newval, void *extra)
     245 ECB             : {
     246 GIC       15715 :     int        *myextra = (int *) extra;
     247                 : 
     248           15715 :     DateStyle = myextra[0];
     249           15715 :     DateOrder = myextra[1];
     250           15715 : }
     251                 : 
     252 ECB             : 
     253                 : /*
     254                 :  * TIMEZONE
     255                 :  */
     256                 : 
     257                 : /*
     258                 :  * check_timezone: GUC check_hook for timezone
     259                 :  */
     260                 : bool
     261 GIC        8068 : check_timezone(char **newval, void **extra, GucSource source)
     262                 : {
     263                 :     pg_tz      *new_tz;
     264                 :     long        gmtoffset;
     265                 :     char       *endptr;
     266                 :     double      hours;
     267                 : 
     268            8068 :     if (pg_strncasecmp(*newval, "interval", 8) == 0)
     269 ECB             :     {
     270                 :         /*
     271                 :          * Support INTERVAL 'foo'.  This is for SQL spec compliance, not
     272                 :          * because it has any actual real-world usefulness.
     273                 :          */
     274 UIC           0 :         const char *valueptr = *newval;
     275                 :         char       *val;
     276 ECB             :         Interval   *interval;
     277                 : 
     278 UIC           0 :         valueptr += 8;
     279               0 :         while (isspace((unsigned char) *valueptr))
     280               0 :             valueptr++;
     281               0 :         if (*valueptr++ != '\'')
     282 UBC           0 :             return false;
     283 UIC           0 :         val = pstrdup(valueptr);
     284                 :         /* Check and remove trailing quote */
     285               0 :         endptr = strchr(val, '\'');
     286 UBC           0 :         if (!endptr || endptr[1] != '\0')
     287 EUB             :         {
     288 UBC           0 :             pfree(val);
     289               0 :             return false;
     290 EUB             :         }
     291 UBC           0 :         *endptr = '\0';
     292                 : 
     293 EUB             :         /*
     294                 :          * Try to parse it.  XXX an invalid interval format will result in
     295                 :          * ereport(ERROR), which is not desirable for GUC.  We did what we
     296                 :          * could to guard against this in flatten_set_variable_args, but a
     297                 :          * string coming in from postgresql.conf might contain anything.
     298                 :          */
     299 UBC           0 :         interval = DatumGetIntervalP(DirectFunctionCall3(interval_in,
     300                 :                                                          CStringGetDatum(val),
     301                 :                                                          ObjectIdGetDatum(InvalidOid),
     302                 :                                                          Int32GetDatum(-1)));
     303                 : 
     304 UIC           0 :         pfree(val);
     305               0 :         if (interval->month != 0)
     306                 :         {
     307 UBC           0 :             GUC_check_errdetail("Cannot specify months in time zone interval.");
     308 UIC           0 :             pfree(interval);
     309               0 :             return false;
     310                 :         }
     311               0 :         if (interval->day != 0)
     312 EUB             :         {
     313 UBC           0 :             GUC_check_errdetail("Cannot specify days in time zone interval.");
     314 UIC           0 :             pfree(interval);
     315 UBC           0 :             return false;
     316 EUB             :         }
     317                 : 
     318                 :         /* Here we change from SQL to Unix sign convention */
     319 UBC           0 :         gmtoffset = -(interval->time / USECS_PER_SEC);
     320 UIC           0 :         new_tz = pg_tzset_offset(gmtoffset);
     321 EUB             : 
     322 UBC           0 :         pfree(interval);
     323 EUB             :     }
     324                 :     else
     325                 :     {
     326                 :         /*
     327                 :          * Try it as a numeric number of hours (possibly fractional).
     328                 :          */
     329 GIC        8068 :         hours = strtod(*newval, &endptr);
     330 GBC        8068 :         if (endptr != *newval && *endptr == '\0')
     331                 :         {
     332                 :             /* Here we change from SQL to Unix sign convention */
     333 GIC          33 :             gmtoffset = -hours * SECS_PER_HOUR;
     334              33 :             new_tz = pg_tzset_offset(gmtoffset);
     335                 :         }
     336                 :         else
     337 ECB             :         {
     338                 :             /*
     339                 :              * Otherwise assume it is a timezone name, and try to load it.
     340                 :              */
     341 CBC        8035 :             new_tz = pg_tzset(*newval);
     342 ECB             : 
     343 GIC        8035 :             if (!new_tz)
     344                 :             {
     345                 :                 /* Doesn't seem to be any great value in errdetail here */
     346 UIC           0 :                 return false;
     347                 :             }
     348                 : 
     349 CBC        8035 :             if (!pg_tz_acceptable(new_tz))
     350                 :             {
     351 LBC           0 :                 GUC_check_errmsg("time zone \"%s\" appears to use leap seconds",
     352                 :                                  *newval);
     353 UIC           0 :                 GUC_check_errdetail("PostgreSQL does not support leap seconds.");
     354 UBC           0 :                 return false;
     355                 :             }
     356                 :         }
     357 ECB             :     }
     358                 : 
     359 EUB             :     /* Test for failure in pg_tzset_offset, which we assume is out-of-range */
     360 GIC        8068 :     if (!new_tz)
     361 EUB             :     {
     362 UBC           0 :         GUC_check_errdetail("UTC timezone offset is out of range.");
     363 UIC           0 :         return false;
     364                 :     }
     365                 : 
     366                 :     /*
     367                 :      * Pass back data for assign_timezone to use
     368 ECB             :      */
     369 GNC        8068 :     *extra = guc_malloc(LOG, sizeof(pg_tz *));
     370 GBC        8068 :     if (!*extra)
     371 UBC           0 :         return false;
     372 GIC        8068 :     *((pg_tz **) *extra) = new_tz;
     373                 : 
     374            8068 :     return true;
     375                 : }
     376                 : 
     377 ECB             : /*
     378                 :  * assign_timezone: GUC assign_hook for timezone
     379 EUB             :  */
     380 ECB             : void
     381 GIC        8110 : assign_timezone(const char *newval, void *extra)
     382 ECB             : {
     383 GIC        8110 :     session_timezone = *((pg_tz **) extra);
     384            8110 : }
     385                 : 
     386                 : /*
     387                 :  * show_timezone: GUC show_hook for timezone
     388                 :  */
     389 ECB             : const char *
     390 GIC       18359 : show_timezone(void)
     391 ECB             : {
     392                 :     const char *tzn;
     393                 : 
     394                 :     /* Always show the zone's canonical name */
     395 GIC       18359 :     tzn = pg_get_timezone_name(session_timezone);
     396                 : 
     397           18359 :     if (tzn != NULL)
     398 CBC       18359 :         return tzn;
     399                 : 
     400 UIC           0 :     return "unknown";
     401                 : }
     402                 : 
     403 ECB             : 
     404                 : /*
     405                 :  * LOG_TIMEZONE
     406                 :  *
     407                 :  * For log_timezone, we don't support the interval-based methods of setting a
     408 EUB             :  * zone, which are only there for SQL spec compliance not because they're
     409                 :  * actually useful.
     410                 :  */
     411                 : 
     412                 : /*
     413                 :  * check_log_timezone: GUC check_hook for log_timezone
     414                 :  */
     415                 : bool
     416 GIC        6016 : check_log_timezone(char **newval, void **extra, GucSource source)
     417                 : {
     418                 :     pg_tz      *new_tz;
     419                 : 
     420                 :     /*
     421                 :      * Assume it is a timezone name, and try to load it.
     422                 :      */
     423            6016 :     new_tz = pg_tzset(*newval);
     424 ECB             : 
     425 GIC        6016 :     if (!new_tz)
     426                 :     {
     427                 :         /* Doesn't seem to be any great value in errdetail here */
     428 UIC           0 :         return false;
     429                 :     }
     430                 : 
     431 CBC        6016 :     if (!pg_tz_acceptable(new_tz))
     432                 :     {
     433 LBC           0 :         GUC_check_errmsg("time zone \"%s\" appears to use leap seconds",
     434                 :                          *newval);
     435 UIC           0 :         GUC_check_errdetail("PostgreSQL does not support leap seconds.");
     436 UBC           0 :         return false;
     437                 :     }
     438                 : 
     439 ECB             :     /*
     440                 :      * Pass back data for assign_log_timezone to use
     441 EUB             :      */
     442 GNC        6016 :     *extra = guc_malloc(LOG, sizeof(pg_tz *));
     443 GBC        6016 :     if (!*extra)
     444 UBC           0 :         return false;
     445 GIC        6016 :     *((pg_tz **) *extra) = new_tz;
     446                 : 
     447            6016 :     return true;
     448                 : }
     449                 : 
     450 ECB             : /*
     451                 :  * assign_log_timezone: GUC assign_hook for log_timezone
     452 EUB             :  */
     453 ECB             : void
     454 GIC        6013 : assign_log_timezone(const char *newval, void *extra)
     455 ECB             : {
     456 GIC        6013 :     log_timezone = *((pg_tz **) extra);
     457            6013 : }
     458                 : 
     459                 : /*
     460                 :  * show_log_timezone: GUC show_hook for log_timezone
     461                 :  */
     462 ECB             : const char *
     463 GIC        1088 : show_log_timezone(void)
     464 ECB             : {
     465                 :     const char *tzn;
     466                 : 
     467                 :     /* Always show the zone's canonical name */
     468 GIC        1088 :     tzn = pg_get_timezone_name(log_timezone);
     469                 : 
     470            1088 :     if (tzn != NULL)
     471 CBC        1088 :         return tzn;
     472                 : 
     473 UIC           0 :     return "unknown";
     474                 : }
     475                 : 
     476 ECB             : 
     477                 : /*
     478                 :  * TIMEZONE_ABBREVIATIONS
     479                 :  */
     480                 : 
     481                 : /*
     482                 :  * GUC check_hook for assign_timezone_abbreviations
     483                 :  */
     484                 : bool
     485 GNC        9732 : check_timezone_abbreviations(char **newval, void **extra, GucSource source)
     486                 : {
     487                 :     /*
     488                 :      * The boot_val for timezone_abbreviations is NULL.  When we see that we
     489                 :      * just do nothing.  If the value isn't overridden from the config file
     490                 :      * then pg_timezone_abbrev_initialize() will eventually replace it with
     491                 :      * "Default".  This hack has two purposes: to avoid wasting cycles loading
     492                 :      * values that might soon be overridden from the config file, and to avoid
     493                 :      * trying to read the timezone abbrev files during InitializeGUCOptions().
     494                 :      * The latter doesn't work in an EXEC_BACKEND subprocess because
     495                 :      * my_exec_path hasn't been set yet and so we can't locate PGSHAREDIR.
     496                 :      */
     497            9732 :     if (*newval == NULL)
     498                 :     {
     499            3155 :         Assert(source == PGC_S_DEFAULT);
     500            3155 :         return true;
     501                 :     }
     502                 : 
     503                 :     /* OK, load the file and produce a guc_malloc'd TimeZoneAbbrevTable */
     504            6577 :     *extra = load_tzoffsets(*newval);
     505                 : 
     506                 :     /* tzparser.c returns NULL on failure, reporting via GUC_check_errmsg */
     507            6577 :     if (!*extra)
     508 UNC           0 :         return false;
     509                 : 
     510 GNC        6577 :     return true;
     511                 : }
     512                 : 
     513                 : /*
     514                 :  * GUC assign_hook for assign_timezone_abbreviations
     515                 :  */
     516                 : void
     517            9644 : assign_timezone_abbreviations(const char *newval, void *extra)
     518                 : {
     519                 :     /* Do nothing for the boot_val default of NULL */
     520            9644 :     if (!extra)
     521            3155 :         return;
     522                 : 
     523            6489 :     InstallTimeZoneAbbrevs((TimeZoneAbbrevTable *) extra);
     524                 : }
     525                 : 
     526                 : 
     527                 : /*
     528 ECB             :  * SET TRANSACTION READ ONLY and SET TRANSACTION READ WRITE
     529                 :  *
     530                 :  * We allow idempotent changes (r/w -> r/w and r/o -> r/o) at any time, and
     531 EUB             :  * we also always allow changes from read-write to read-only.  However,
     532                 :  * read-only may be changed to read-write only when in a top-level transaction
     533                 :  * that has not yet taken an initial snapshot.  Can't do it in a hot standby,
     534                 :  * either.
     535                 :  *
     536                 :  * If we are not in a transaction at all, just allow the change; it means
     537                 :  * nothing since XactReadOnly will be reset by the next StartTransaction().
     538                 :  * The IsTransactionState() test protects us against trying to check
     539                 :  * RecoveryInProgress() in contexts where shared memory is not accessible.
     540                 :  * (Similarly, if we're restoring state in a parallel worker, just allow
     541                 :  * the change.)
     542                 :  */
     543 ECB             : bool
     544 GIC        6943 : check_transaction_read_only(bool *newval, void **extra, GucSource source)
     545                 : {
     546            6943 :     if (*newval == false && XactReadOnly && IsTransactionState() && !InitializingParallelWorker)
     547                 :     {
     548                 :         /* Can't go to r/w mode inside a r/o transaction */
     549              29 :         if (IsSubTransaction())
     550                 :         {
     551               6 :             GUC_check_errcode(ERRCODE_ACTIVE_SQL_TRANSACTION);
     552               6 :             GUC_check_errmsg("cannot set transaction read-write mode inside a read-only transaction");
     553               6 :             return false;
     554                 :         }
     555 ECB             :         /* Top level transaction can't change to r/w after first snapshot. */
     556 GIC          23 :         if (FirstSnapshotSet)
     557 ECB             :         {
     558 CBC           3 :             GUC_check_errcode(ERRCODE_ACTIVE_SQL_TRANSACTION);
     559 GIC           3 :             GUC_check_errmsg("transaction read-write mode must be set before any query");
     560               3 :             return false;
     561                 :         }
     562 ECB             :         /* Can't go to r/w mode while recovery is still active */
     563 GIC          20 :         if (RecoveryInProgress())
     564                 :         {
     565 LBC           0 :             GUC_check_errcode(ERRCODE_FEATURE_NOT_SUPPORTED);
     566 UBC           0 :             GUC_check_errmsg("cannot set transaction read-write mode during recovery");
     567 UIC           0 :             return false;
     568 ECB             :         }
     569                 :     }
     570                 : 
     571 GIC        6934 :     return true;
     572                 : }
     573                 : 
     574                 : /*
     575 ECB             :  * SET TRANSACTION ISOLATION LEVEL
     576                 :  *
     577                 :  * We allow idempotent changes at any time, but otherwise this can only be
     578                 :  * changed in a toplevel transaction that has not yet taken a snapshot.
     579                 :  *
     580                 :  * As in check_transaction_read_only, allow it if not inside a transaction.
     581                 :  */
     582                 : bool
     583 GNC        9488 : check_transaction_isolation(int *newval, void **extra, GucSource source)
     584                 : {
     585 GIC        9488 :     int         newXactIsoLevel = *newval;
     586                 : 
     587            9488 :     if (newXactIsoLevel != XactIsoLevel && IsTransactionState())
     588                 :     {
     589            2783 :         if (FirstSnapshotSet)
     590                 :         {
     591               1 :             GUC_check_errcode(ERRCODE_ACTIVE_SQL_TRANSACTION);
     592               1 :             GUC_check_errmsg("SET TRANSACTION ISOLATION LEVEL must be called before any query");
     593               1 :             return false;
     594                 :         }
     595                 :         /* We ignore a subtransaction setting it to the existing value. */
     596            2782 :         if (IsSubTransaction())
     597                 :         {
     598 UIC           0 :             GUC_check_errcode(ERRCODE_ACTIVE_SQL_TRANSACTION);
     599               0 :             GUC_check_errmsg("SET TRANSACTION ISOLATION LEVEL must not be called in a subtransaction");
     600               0 :             return false;
     601                 :         }
     602 ECB             :         /* Can't go to serializable mode while recovery is still active */
     603 GIC        2782 :         if (newXactIsoLevel == XACT_SERIALIZABLE && RecoveryInProgress())
     604 ECB             :         {
     605 UIC           0 :             GUC_check_errcode(ERRCODE_FEATURE_NOT_SUPPORTED);
     606               0 :             GUC_check_errmsg("cannot use serializable mode in a hot standby");
     607 LBC           0 :             GUC_check_errhint("You can use REPEATABLE READ instead.");
     608 UIC           0 :             return false;
     609 ECB             :         }
     610                 :     }
     611                 : 
     612 GIC        9487 :     return true;
     613                 : }
     614 ECB             : 
     615                 : /*
     616                 :  * SET TRANSACTION [NOT] DEFERRABLE
     617                 :  */
     618                 : 
     619                 : bool
     620 GIC        6334 : check_transaction_deferrable(bool *newval, void **extra, GucSource source)
     621 ECB             : {
     622 GIC        6334 :     if (IsSubTransaction())
     623 EUB             :     {
     624 UBC           0 :         GUC_check_errcode(ERRCODE_ACTIVE_SQL_TRANSACTION);
     625               0 :         GUC_check_errmsg("SET TRANSACTION [NOT] DEFERRABLE cannot be called within a subtransaction");
     626 UIC           0 :         return false;
     627                 :     }
     628 GIC        6334 :     if (FirstSnapshotSet)
     629 ECB             :     {
     630 UIC           0 :         GUC_check_errcode(ERRCODE_ACTIVE_SQL_TRANSACTION);
     631               0 :         GUC_check_errmsg("SET TRANSACTION [NOT] DEFERRABLE must be called before any query");
     632               0 :         return false;
     633                 :     }
     634                 : 
     635 GIC        6334 :     return true;
     636                 : }
     637                 : 
     638                 : /*
     639                 :  * Random number seed
     640                 :  *
     641 ECB             :  * We can't roll back the random sequence on error, and we don't want
     642                 :  * config file reloads to affect it, so we only want interactive SET SEED
     643                 :  * commands to set it.  We use the "extra" storage to ensure that rollbacks
     644                 :  * don't try to do the operation again.
     645                 :  */
     646                 : 
     647                 : bool
     648 GIC        1857 : check_random_seed(double *newval, void **extra, GucSource source)
     649 ECB             : {
     650 GNC        1857 :     *extra = guc_malloc(LOG, sizeof(int));
     651 CBC        1857 :     if (!*extra)
     652 UIC           0 :         return false;
     653                 :     /* Arm the assign only if source of value is an interactive SET */
     654 CBC        1857 :     *((int *) *extra) = (source >= PGC_S_INTERACTIVE);
     655                 : 
     656 GBC        1857 :     return true;
     657 EUB             : }
     658                 : 
     659                 : void
     660 GIC        1857 : assign_random_seed(double newval, void *extra)
     661 ECB             : {
     662                 :     /* We'll do this at most once for any setting of the GUC variable */
     663 GBC        1857 :     if (*((int *) extra))
     664 UBC           0 :         DirectFunctionCall1(setseed, Float8GetDatum(newval));
     665 GBC        1857 :     *((int *) extra) = 0;
     666            1857 : }
     667                 : 
     668                 : const char *
     669 UIC           0 : show_random_seed(void)
     670 ECB             : {
     671 UIC           0 :     return "unavailable";
     672                 : }
     673                 : 
     674                 : 
     675                 : /*
     676                 :  * SET CLIENT_ENCODING
     677                 :  */
     678 ECB             : 
     679                 : bool
     680 CBC       15595 : check_client_encoding(char **newval, void **extra, GucSource source)
     681                 : {
     682 EUB             :     int         encoding;
     683                 :     const char *canonical_name;
     684                 : 
     685                 :     /* Look up the encoding by name */
     686 CBC       15595 :     encoding = pg_valid_client_encoding(*newval);
     687 GIC       15595 :     if (encoding < 0)
     688 UBC           0 :         return false;
     689 EUB             : 
     690                 :     /* Get the canonical name (no aliases, uniform case) */
     691 GIC       15595 :     canonical_name = pg_encoding_to_char(encoding);
     692                 : 
     693 ECB             :     /*
     694                 :      * If we are not within a transaction then PrepareClientEncoding will not
     695                 :      * be able to look up the necessary conversion procs.  If we are still
     696                 :      * starting up, it will return "OK" anyway, and InitializeClientEncoding
     697                 :      * will fix things once initialization is far enough along.  After
     698                 :      * startup, we'll fail.  This would only happen if someone tries to change
     699                 :      * client_encoding in postgresql.conf and then SIGHUP existing sessions.
     700                 :      * It seems like a bad idea for client_encoding to change that way anyhow,
     701                 :      * so we don't go out of our way to support it.
     702                 :      *
     703                 :      * Note: in the postmaster, or any other process that never calls
     704                 :      * InitializeClientEncoding, PrepareClientEncoding will always succeed,
     705                 :      * and so will SetClientEncoding; but they won't do anything, which is OK.
     706                 :      */
     707 GIC       15595 :     if (PrepareClientEncoding(encoding) < 0)
     708 ECB             :     {
     709 LBC           0 :         if (IsTransactionState())
     710 EUB             :         {
     711                 :             /* Must be a genuine no-such-conversion problem */
     712 LBC           0 :             GUC_check_errcode(ERRCODE_FEATURE_NOT_SUPPORTED);
     713 UIC           0 :             GUC_check_errdetail("Conversion between %s and %s is not supported.",
     714 ECB             :                                 canonical_name,
     715                 :                                 GetDatabaseEncodingName());
     716                 :         }
     717                 :         else
     718                 :         {
     719                 :             /* Provide a useful complaint */
     720 UIC           0 :             GUC_check_errdetail("Cannot change \"client_encoding\" now.");
     721 ECB             :         }
     722 UBC           0 :         return false;
     723 ECB             :     }
     724                 : 
     725                 :     /*
     726                 :      * Replace the user-supplied string with the encoding's canonical name.
     727 EUB             :      * This gets rid of aliases and case-folding variations.
     728                 :      *
     729                 :      * XXX Although canonicalizing seems like a good idea in the abstract, it
     730                 :      * breaks pre-9.1 JDBC drivers, which expect that if they send "UNICODE"
     731                 :      * as the client_encoding setting then it will read back the same way. As
     732                 :      * a workaround, don't replace the string if it's "UNICODE".  Remove that
     733                 :      * hack when pre-9.1 JDBC drivers are no longer in use.
     734                 :      */
     735 GIC       15595 :     if (strcmp(*newval, canonical_name) != 0 &&
     736              14 :         strcmp(*newval, "UNICODE") != 0)
     737                 :     {
     738 GNC          14 :         guc_free(*newval);
     739              14 :         *newval = guc_strdup(LOG, canonical_name);
     740 GIC          14 :         if (!*newval)
     741 UIC           0 :             return false;
     742                 :     }
     743                 : 
     744 ECB             :     /*
     745                 :      * Save the encoding's ID in *extra, for use by assign_client_encoding.
     746 EUB             :      */
     747 GNC       15595 :     *extra = guc_malloc(LOG, sizeof(int));
     748 GIC       15595 :     if (!*extra)
     749 LBC           0 :         return false;
     750 GIC       15595 :     *((int *) *extra) = encoding;
     751                 : 
     752           15595 :     return true;
     753                 : }
     754                 : 
     755                 : void
     756           15503 : assign_client_encoding(const char *newval, void *extra)
     757                 : {
     758           15503 :     int         encoding = *((int *) extra);
     759                 : 
     760                 :     /*
     761                 :      * Parallel workers send data to the leader, not the client.  They always
     762                 :      * send data using the database encoding.
     763                 :      */
     764           15503 :     if (IsParallelWorker())
     765 ECB             :     {
     766                 :         /*
     767 EUB             :          * During parallel worker startup, we want to accept the leader's
     768                 :          * client_encoding setting so that anyone who looks at the value in
     769                 :          * the worker sees the same value that they would see in the leader.
     770                 :          */
     771 GBC        3894 :         if (InitializingParallelWorker)
     772 GIC        3894 :             return;
     773                 : 
     774                 :         /*
     775                 :          * A change other than during startup, for example due to a SET clause
     776                 :          * attached to a function definition, should be rejected, as there is
     777                 :          * nothing we can do inside the worker to make it take effect.
     778 EUB             :          */
     779 UIC           0 :         ereport(ERROR,
     780 EUB             :                 (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
     781                 :                  errmsg("cannot change client_encoding during a parallel operation")));
     782                 :     }
     783                 : 
     784                 :     /* We do not expect an error if PrepareClientEncoding succeeded */
     785 GIC       11609 :     if (SetClientEncoding(encoding) < 0)
     786 UIC           0 :         elog(LOG, "SetClientEncoding(%d) failed", encoding);
     787                 : }
     788                 : 
     789                 : 
     790                 : /*
     791                 :  * SET SESSION AUTHORIZATION
     792                 :  */
     793 ECB             : 
     794                 : typedef struct
     795                 : {
     796                 :     /* This is the "extra" state for both SESSION AUTHORIZATION and ROLE */
     797                 :     Oid         roleid;
     798                 :     bool        is_superuser;
     799 EUB             : } role_auth_extra;
     800                 : 
     801                 : bool
     802 GIC       15805 : check_session_authorization(char **newval, void **extra, GucSource source)
     803                 : {
     804                 :     HeapTuple   roleTup;
     805 ECB             :     Form_pg_authid roleform;
     806                 :     Oid         roleid;
     807 EUB             :     bool        is_superuser;
     808 ECB             :     role_auth_extra *myextra;
     809                 : 
     810                 :     /* Do nothing for the boot_val default of NULL */
     811 GIC       15805 :     if (*newval == NULL)
     812            3155 :         return true;
     813                 : 
     814 CBC       12650 :     if (!IsTransactionState())
     815                 :     {
     816 ECB             :         /*
     817                 :          * Can't do catalog lookups, so fail.  The result of this is that
     818                 :          * session_authorization cannot be set in postgresql.conf, which seems
     819                 :          * like a good thing anyway, so we don't work hard to avoid it.
     820                 :          */
     821 UIC           0 :         return false;
     822 ECB             :     }
     823                 : 
     824                 :     /* Look up the username */
     825 GIC       12650 :     roleTup = SearchSysCache1(AUTHNAME, PointerGetDatum(*newval));
     826           12650 :     if (!HeapTupleIsValid(roleTup))
     827                 :     {
     828                 :         /*
     829 ECB             :          * When source == PGC_S_TEST, we don't throw a hard error for a
     830                 :          * nonexistent user name, only a NOTICE.  See comments in guc.h.
     831                 :          */
     832 UIC           0 :         if (source == PGC_S_TEST)
     833                 :         {
     834               0 :             ereport(NOTICE,
     835                 :                     (errcode(ERRCODE_UNDEFINED_OBJECT),
     836                 :                      errmsg("role \"%s\" does not exist", *newval)));
     837 UBC           0 :             return true;
     838                 :         }
     839 UIC           0 :         GUC_check_errmsg("role \"%s\" does not exist", *newval);
     840               0 :         return false;
     841                 :     }
     842                 : 
     843 CBC       12650 :     roleform = (Form_pg_authid) GETSTRUCT(roleTup);
     844 GBC       12650 :     roleid = roleform->oid;
     845 GIC       12650 :     is_superuser = roleform->rolsuper;
     846                 : 
     847           12650 :     ReleaseSysCache(roleTup);
     848                 : 
     849                 :     /* Set up "extra" struct for assign_session_authorization to use */
     850 GNC       12650 :     myextra = (role_auth_extra *) guc_malloc(LOG, sizeof(role_auth_extra));
     851 GIC       12650 :     if (!myextra)
     852 UIC           0 :         return false;
     853 GIC       12650 :     myextra->roleid = roleid;
     854           12650 :     myextra->is_superuser = is_superuser;
     855           12650 :     *extra = (void *) myextra;
     856                 : 
     857           12650 :     return true;
     858                 : }
     859                 : 
     860 ECB             : void
     861 GIC       16227 : assign_session_authorization(const char *newval, void *extra)
     862                 : {
     863           16227 :     role_auth_extra *myextra = (role_auth_extra *) extra;
     864                 : 
     865                 :     /* Do nothing for the boot_val default of NULL */
     866           16227 :     if (!myextra)
     867            3155 :         return;
     868                 : 
     869 CBC       13072 :     SetSessionAuthorization(myextra->roleid, myextra->is_superuser);
     870 ECB             : }
     871                 : 
     872                 : 
     873                 : /*
     874                 :  * SET ROLE
     875                 :  *
     876                 :  * The SQL spec requires "SET ROLE NONE" to unset the role, so we hardwire
     877                 :  * a translation of "none" to InvalidOid.  Otherwise this is much like
     878                 :  * SET SESSION AUTHORIZATION.
     879 EUB             :  */
     880                 : extern char *role_string;       /* in guc_tables.c */
     881                 : 
     882                 : bool
     883 CBC        2257 : check_role(char **newval, void **extra, GucSource source)
     884 ECB             : {
     885                 :     HeapTuple   roleTup;
     886                 :     Oid         roleid;
     887                 :     bool        is_superuser;
     888                 :     role_auth_extra *myextra;
     889                 :     Form_pg_authid roleform;
     890 EUB             : 
     891 GIC        2257 :     if (strcmp(*newval, "none") == 0)
     892 EUB             :     {
     893                 :         /* hardwired translation */
     894 GIC        1857 :         roleid = InvalidOid;
     895 GBC        1857 :         is_superuser = false;
     896                 :     }
     897 EUB             :     else
     898                 :     {
     899 GIC         400 :         if (!IsTransactionState())
     900                 :         {
     901 ECB             :             /*
     902                 :              * Can't do catalog lookups, so fail.  The result of this is that
     903                 :              * role cannot be set in postgresql.conf, which seems like a good
     904                 :              * thing anyway, so we don't work hard to avoid it.
     905                 :              */
     906 UIC           0 :             return false;
     907                 :         }
     908 ECB             : 
     909                 :         /*
     910 EUB             :          * When source == PGC_S_TEST, we don't throw a hard error for a
     911 ECB             :          * nonexistent user name or insufficient privileges, only a NOTICE.
     912                 :          * See comments in guc.h.
     913                 :          */
     914                 : 
     915                 :         /* Look up the username */
     916 GIC         400 :         roleTup = SearchSysCache1(AUTHNAME, PointerGetDatum(*newval));
     917             400 :         if (!HeapTupleIsValid(roleTup))
     918                 :         {
     919 LBC           0 :             if (source == PGC_S_TEST)
     920                 :             {
     921               0 :                 ereport(NOTICE,
     922                 :                         (errcode(ERRCODE_UNDEFINED_OBJECT),
     923                 :                          errmsg("role \"%s\" does not exist", *newval)));
     924               0 :                 return true;
     925 ECB             :             }
     926 UIC           0 :             GUC_check_errmsg("role \"%s\" does not exist", *newval);
     927 LBC           0 :             return false;
     928                 :         }
     929                 : 
     930 GIC         400 :         roleform = (Form_pg_authid) GETSTRUCT(roleTup);
     931             400 :         roleid = roleform->oid;
     932             400 :         is_superuser = roleform->rolsuper;
     933                 : 
     934             400 :         ReleaseSysCache(roleTup);
     935                 : 
     936                 :         /*
     937                 :          * Verify that session user is allowed to become this role, but skip
     938                 :          * this in parallel mode, where we must blindly recreate the parallel
     939                 :          * leader's state.
     940                 :          */
     941 CBC         400 :         if (!InitializingParallelWorker &&
     942 GNC         400 :             !member_can_set_role(GetSessionUserId(), roleid))
     943                 :         {
     944 GIC           6 :             if (source == PGC_S_TEST)
     945                 :             {
     946 UIC           0 :                 ereport(NOTICE,
     947                 :                         (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
     948                 :                          errmsg("permission will be denied to set role \"%s\"",
     949 ECB             :                                 *newval)));
     950 UIC           0 :                 return true;
     951                 :             }
     952 CBC           6 :             GUC_check_errcode(ERRCODE_INSUFFICIENT_PRIVILEGE);
     953               6 :             GUC_check_errmsg("permission denied to set role \"%s\"",
     954                 :                              *newval);
     955 GIC           6 :             return false;
     956                 :         }
     957 ECB             :     }
     958                 : 
     959                 :     /* Set up "extra" struct for assign_role to use */
     960 GNC        2251 :     myextra = (role_auth_extra *) guc_malloc(LOG, sizeof(role_auth_extra));
     961 GIC        2251 :     if (!myextra)
     962 UIC           0 :         return false;
     963 GIC        2251 :     myextra->roleid = roleid;
     964 GBC        2251 :     myextra->is_superuser = is_superuser;
     965 GIC        2251 :     *extra = (void *) myextra;
     966                 : 
     967            2251 :     return true;
     968                 : }
     969                 : 
     970                 : void
     971            2537 : assign_role(const char *newval, void *extra)
     972                 : {
     973            2537 :     role_auth_extra *myextra = (role_auth_extra *) extra;
     974 ECB             : 
     975 CBC        2537 :     SetCurrentRoleId(myextra->roleid, myextra->is_superuser);
     976 GIC        2537 : }
     977 EUB             : 
     978                 : const char *
     979 UBC           0 : show_role(void)
     980                 : {
     981                 :     /*
     982 EUB             :      * Check whether SET ROLE is active; if not return "none".  This is a
     983                 :      * kluge to deal with the fact that SET SESSION AUTHORIZATION logically
     984                 :      * resets SET ROLE to NONE, but we cannot set the GUC role variable from
     985                 :      * assign_session_authorization (because we haven't got enough info to
     986                 :      * call set_config_option).
     987                 :      */
     988 LBC           0 :     if (!OidIsValid(GetCurrentRoleId()))
     989               0 :         return "none";
     990 ECB             : 
     991                 :     /* Otherwise we can just use the GUC string */
     992 LBC           0 :     return role_string ? role_string : "none";
     993                 : }
     994                 : 
     995                 : 
     996                 : /*
     997                 :  * PATH VARIABLES
     998                 :  *
     999                 :  * check_canonical_path is used for log_directory and some other GUCs where
    1000                 :  * all we want to do is canonicalize the represented path name.
    1001                 :  */
    1002                 : 
    1003                 : bool
    1004 GNC        3714 : check_canonical_path(char **newval, void **extra, GucSource source)
    1005                 : {
    1006                 :     /*
    1007                 :      * Since canonicalize_path never enlarges the string, we can just modify
    1008                 :      * newval in-place.  But watch out for NULL, which is the default value
    1009                 :      * for external_pid_file.
    1010                 :      */
    1011            3714 :     if (*newval)
    1012            1857 :         canonicalize_path(*newval);
    1013            3714 :     return true;
    1014                 : }
    1015                 : 
    1016                 : 
    1017                 : /*
    1018                 :  * MISCELLANEOUS
    1019                 :  */
    1020                 : 
    1021                 : /*
    1022                 :  * GUC check_hook for application_name
    1023                 :  */
    1024                 : bool
    1025           12138 : check_application_name(char **newval, void **extra, GucSource source)
    1026                 : {
    1027                 :     char       *clean;
    1028                 :     char       *ret;
    1029                 : 
    1030                 :     /* Only allow clean ASCII chars in the application name */
    1031           12138 :     clean = pg_clean_ascii(*newval, MCXT_ALLOC_NO_OOM);
    1032           12138 :     if (!clean)
    1033 UNC           0 :         return false;
    1034                 : 
    1035 GNC       12138 :     ret = guc_strdup(WARNING, clean);
    1036           12138 :     if (!ret)
    1037                 :     {
    1038 UNC           0 :         pfree(clean);
    1039               0 :         return false;
    1040                 :     }
    1041                 : 
    1042 GNC       12138 :     pfree(clean);
    1043           12138 :     *newval = ret;
    1044           12138 :     return true;
    1045                 : }
    1046                 : 
    1047                 : /*
    1048                 :  * GUC assign_hook for application_name
    1049                 :  */
    1050                 : void
    1051           12124 : assign_application_name(const char *newval, void *extra)
    1052                 : {
    1053                 :     /* Update the pg_stat_activity view */
    1054           12124 :     pgstat_report_appname(newval);
    1055           12124 : }
    1056                 : 
    1057                 : /*
    1058                 :  * GUC check_hook for cluster_name
    1059                 :  */
    1060                 : bool
    1061            2357 : check_cluster_name(char **newval, void **extra, GucSource source)
    1062                 : {
    1063                 :     char       *clean;
    1064                 :     char       *ret;
    1065                 : 
    1066                 :     /* Only allow clean ASCII chars in the cluster name */
    1067            2357 :     clean = pg_clean_ascii(*newval, MCXT_ALLOC_NO_OOM);
    1068            2357 :     if (!clean)
    1069 UNC           0 :         return false;
    1070                 : 
    1071 GNC        2357 :     ret = guc_strdup(WARNING, clean);
    1072            2357 :     if (!ret)
    1073                 :     {
    1074 UNC           0 :         pfree(clean);
    1075               0 :         return false;
    1076                 :     }
    1077                 : 
    1078 GNC        2357 :     pfree(clean);
    1079            2357 :     *newval = ret;
    1080            2357 :     return true;
    1081                 : }
    1082                 : 
    1083                 : /*
    1084                 :  * GUC assign_hook for maintenance_io_concurrency
    1085                 :  */
    1086                 : void
    1087            1857 : assign_maintenance_io_concurrency(int newval, void *extra)
    1088                 : {
    1089                 : #ifdef USE_PREFETCH
    1090                 :     /*
    1091                 :      * Reconfigure recovery prefetching, because a setting it depends on
    1092                 :      * changed.
    1093                 :      */
    1094            1857 :     maintenance_io_concurrency = newval;
    1095            1857 :     if (AmStartupProcess())
    1096 UNC           0 :         XLogPrefetchReconfigure();
    1097                 : #endif
    1098 GNC        1857 : }
    1099                 : 
    1100                 : 
    1101                 : /*
    1102                 :  * These show hooks just exist because we want to show the values in octal.
    1103                 :  */
    1104                 : 
    1105                 : /*
    1106                 :  * GUC show_hook for data_directory_mode
    1107                 :  */
    1108                 : const char *
    1109            1382 : show_data_directory_mode(void)
    1110                 : {
    1111                 :     static char buf[12];
    1112                 : 
    1113            1382 :     snprintf(buf, sizeof(buf), "%04o", data_directory_mode);
    1114            1382 :     return buf;
    1115                 : }
    1116                 : 
    1117                 : /*
    1118                 :  * GUC show_hook for log_file_mode
    1119                 :  */
    1120                 : const char *
    1121            1088 : show_log_file_mode(void)
    1122                 : {
    1123                 :     static char buf[12];
    1124                 : 
    1125            1088 :     snprintf(buf, sizeof(buf), "%04o", Log_file_mode);
    1126            1088 :     return buf;
    1127                 : }
    1128                 : 
    1129                 : /*
    1130                 :  * GUC show_hook for unix_socket_permissions
    1131                 :  */
    1132                 : const char *
    1133            1088 : show_unix_socket_permissions(void)
    1134                 : {
    1135                 :     static char buf[12];
    1136                 : 
    1137            1088 :     snprintf(buf, sizeof(buf), "%04o", Unix_socket_permissions);
    1138            1088 :     return buf;
    1139                 : }
    1140                 : 
    1141                 : 
    1142                 : /*
    1143                 :  * These check hooks do nothing more than reject non-default settings
    1144                 :  * in builds that don't support them.
    1145                 :  */
    1146                 : 
    1147                 : bool
    1148            1857 : check_bonjour(bool *newval, void **extra, GucSource source)
    1149                 : {
    1150                 : #ifndef USE_BONJOUR
    1151            1857 :     if (*newval)
    1152                 :     {
    1153 UNC           0 :         GUC_check_errmsg("Bonjour is not supported by this build");
    1154               0 :         return false;
    1155                 :     }
    1156                 : #endif
    1157 GNC        1857 :     return true;
    1158                 : }
    1159                 : 
    1160                 : bool
    1161            1863 : check_default_with_oids(bool *newval, void **extra, GucSource source)
    1162                 : {
    1163            1863 :     if (*newval)
    1164                 :     {
    1165                 :         /* check the GUC's definition for an explanation */
    1166               3 :         GUC_check_errcode(ERRCODE_FEATURE_NOT_SUPPORTED);
    1167               3 :         GUC_check_errmsg("tables declared WITH OIDS are not supported");
    1168                 : 
    1169               3 :         return false;
    1170                 :     }
    1171                 : 
    1172            1860 :     return true;
    1173                 : }
    1174                 : 
    1175                 : bool
    1176            2154 : check_effective_io_concurrency(int *newval, void **extra, GucSource source)
    1177                 : {
    1178                 : #ifndef USE_PREFETCH
    1179                 :     if (*newval != 0)
    1180                 :     {
    1181                 :         GUC_check_errdetail("effective_io_concurrency must be set to 0 on platforms that lack posix_fadvise().");
    1182                 :         return false;
    1183                 :     }
    1184                 : #endif                          /* USE_PREFETCH */
    1185            2154 :     return true;
    1186                 : }
    1187                 : 
    1188                 : bool
    1189            1857 : check_maintenance_io_concurrency(int *newval, void **extra, GucSource source)
    1190                 : {
    1191                 : #ifndef USE_PREFETCH
    1192                 :     if (*newval != 0)
    1193                 :     {
    1194                 :         GUC_check_errdetail("maintenance_io_concurrency must be set to 0 on platforms that lack posix_fadvise().");
    1195                 :         return false;
    1196                 :     }
    1197                 : #endif                          /* USE_PREFETCH */
    1198            1857 :     return true;
    1199                 : }
    1200                 : 
    1201                 : bool
    1202            1883 : check_ssl(bool *newval, void **extra, GucSource source)
    1203                 : {
    1204                 : #ifndef USE_SSL
    1205                 :     if (*newval)
    1206                 :     {
    1207                 :         GUC_check_errmsg("SSL is not supported by this build");
    1208                 :         return false;
    1209                 :     }
    1210                 : #endif
    1211            1883 :     return true;
    1212                 : }
        

Generated by: LCOV version v1.16-55-g56c0a2a