LCOV - code coverage report
Current view: top level - src/backend/utils/misc - guc_funcs.c (source / functions) Coverage Total Hit
Test: Code coverage Lines: 76.3 % 460 351
Test Date: 2026-01-26 10:56:24 Functions: 93.8 % 16 15
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 53.8 % 225 121

             Branch data     Line data    Source code
       1                 :             : /*--------------------------------------------------------------------
       2                 :             :  *
       3                 :             :  * guc_funcs.c
       4                 :             :  *
       5                 :             :  * SQL commands and SQL-accessible functions related to GUC variables.
       6                 :             :  *
       7                 :             :  *
       8                 :             :  * Copyright (c) 2000-2026, PostgreSQL Global Development Group
       9                 :             :  * Written by Peter Eisentraut <peter_e@gmx.net>.
      10                 :             :  *
      11                 :             :  * IDENTIFICATION
      12                 :             :  *        src/backend/utils/misc/guc_funcs.c
      13                 :             :  *
      14                 :             :  *--------------------------------------------------------------------
      15                 :             :  */
      16                 :             : #include "postgres.h"
      17                 :             : 
      18                 :             : #include <sys/stat.h>
      19                 :             : #include <unistd.h>
      20                 :             : 
      21                 :             : #include "access/xact.h"
      22                 :             : #include "catalog/objectaccess.h"
      23                 :             : #include "catalog/pg_authid.h"
      24                 :             : #include "catalog/pg_parameter_acl.h"
      25                 :             : #include "funcapi.h"
      26                 :             : #include "guc_internal.h"
      27                 :             : #include "miscadmin.h"
      28                 :             : #include "parser/parse_type.h"
      29                 :             : #include "utils/acl.h"
      30                 :             : #include "utils/builtins.h"
      31                 :             : #include "utils/guc_tables.h"
      32                 :             : #include "utils/snapmgr.h"
      33                 :             : 
      34                 :             : static char *flatten_set_variable_args(const char *name, List *args);
      35                 :             : static void ShowGUCConfigOption(const char *name, DestReceiver *dest);
      36                 :             : static void ShowAllGUCConfig(DestReceiver *dest);
      37                 :             : 
      38                 :             : 
      39                 :             : /*
      40                 :             :  * SET command
      41                 :             :  */
      42                 :             : void
      43                 :        4435 : ExecSetVariableStmt(VariableSetStmt *stmt, bool isTopLevel)
      44                 :             : {
      45                 :        4435 :         GucAction       action = stmt->is_local ? GUC_ACTION_LOCAL : GUC_ACTION_SET;
      46                 :             : 
      47                 :             :         /*
      48                 :             :          * Workers synchronize these parameters at the start of the parallel
      49                 :             :          * operation; then, we block SET during the operation.
      50                 :             :          */
      51         [ +  - ]:        4435 :         if (IsInParallelMode())
      52   [ #  #  #  # ]:           0 :                 ereport(ERROR,
      53                 :             :                                 (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
      54                 :             :                                  errmsg("cannot set parameters during a parallel operation")));
      55                 :             : 
      56   [ +  +  +  +  :        4435 :         switch (stmt->kind)
                   +  - ]
      57                 :             :         {
      58                 :             :                 case VAR_SET_VALUE:
      59                 :             :                 case VAR_SET_CURRENT:
      60         [ +  + ]:        3668 :                         if (stmt->is_local)
      61                 :         299 :                                 WarnNoTransactionBlock(isTopLevel, "SET LOCAL");
      62                 :        7336 :                         (void) set_config_option(stmt->name,
      63                 :        3668 :                                                                          ExtractSetVariableArgs(stmt),
      64                 :        3668 :                                                                          (superuser() ? PGC_SUSET : PGC_USERSET),
      65                 :             :                                                                          PGC_S_SESSION,
      66                 :        3668 :                                                                          action, true, 0, false);
      67                 :        3668 :                         break;
      68                 :             :                 case VAR_SET_MULTI:
      69                 :             : 
      70                 :             :                         /*
      71                 :             :                          * Special-case SQL syntaxes.  The TRANSACTION and SESSION
      72                 :             :                          * CHARACTERISTICS cases effectively set more than one variable
      73                 :             :                          * per statement.  TRANSACTION SNAPSHOT only takes one argument,
      74                 :             :                          * but we put it here anyway since it's a special case and not
      75                 :             :                          * related to any GUC variable.
      76                 :             :                          */
      77         [ +  + ]:          19 :                         if (strcmp(stmt->name, "TRANSACTION") == 0)
      78                 :             :                         {
      79                 :          17 :                                 ListCell   *head;
      80                 :             : 
      81                 :          17 :                                 WarnNoTransactionBlock(isTopLevel, "SET TRANSACTION");
      82                 :             : 
      83   [ +  -  +  +  :          39 :                                 foreach(head, stmt->args)
                   +  + ]
      84                 :             :                                 {
      85                 :          22 :                                         DefElem    *item = (DefElem *) lfirst(head);
      86                 :             : 
      87         [ +  + ]:          22 :                                         if (strcmp(item->defname, "transaction_isolation") == 0)
      88                 :           3 :                                                 SetPGVariable("transaction_isolation",
      89                 :           3 :                                                                           list_make1(item->arg), stmt->is_local);
      90         [ +  + ]:          19 :                                         else if (strcmp(item->defname, "transaction_read_only") == 0)
      91                 :          18 :                                                 SetPGVariable("transaction_read_only",
      92                 :          18 :                                                                           list_make1(item->arg), stmt->is_local);
      93         [ +  - ]:           1 :                                         else if (strcmp(item->defname, "transaction_deferrable") == 0)
      94                 :           1 :                                                 SetPGVariable("transaction_deferrable",
      95                 :           1 :                                                                           list_make1(item->arg), stmt->is_local);
      96                 :             :                                         else
      97   [ #  #  #  # ]:           0 :                                                 elog(ERROR, "unexpected SET TRANSACTION element: %s",
      98                 :             :                                                          item->defname);
      99                 :          22 :                                 }
     100                 :          17 :                         }
     101         [ -  + ]:           2 :                         else if (strcmp(stmt->name, "SESSION CHARACTERISTICS") == 0)
     102                 :             :                         {
     103                 :           2 :                                 ListCell   *head;
     104                 :             : 
     105   [ +  -  +  +  :           4 :                                 foreach(head, stmt->args)
                   +  + ]
     106                 :             :                                 {
     107                 :           2 :                                         DefElem    *item = (DefElem *) lfirst(head);
     108                 :             : 
     109         [ +  - ]:           2 :                                         if (strcmp(item->defname, "transaction_isolation") == 0)
     110                 :           0 :                                                 SetPGVariable("default_transaction_isolation",
     111                 :           0 :                                                                           list_make1(item->arg), stmt->is_local);
     112         [ -  + ]:           2 :                                         else if (strcmp(item->defname, "transaction_read_only") == 0)
     113                 :           2 :                                                 SetPGVariable("default_transaction_read_only",
     114                 :           2 :                                                                           list_make1(item->arg), stmt->is_local);
     115         [ #  # ]:           0 :                                         else if (strcmp(item->defname, "transaction_deferrable") == 0)
     116                 :           0 :                                                 SetPGVariable("default_transaction_deferrable",
     117                 :           0 :                                                                           list_make1(item->arg), stmt->is_local);
     118                 :             :                                         else
     119   [ #  #  #  # ]:           0 :                                                 elog(ERROR, "unexpected SET SESSION element: %s",
     120                 :             :                                                          item->defname);
     121                 :           2 :                                 }
     122                 :           2 :                         }
     123         [ #  # ]:           0 :                         else if (strcmp(stmt->name, "TRANSACTION SNAPSHOT") == 0)
     124                 :             :                         {
     125                 :           0 :                                 A_Const    *con = linitial_node(A_Const, stmt->args);
     126                 :             : 
     127         [ #  # ]:           0 :                                 if (stmt->is_local)
     128   [ #  #  #  # ]:           0 :                                         ereport(ERROR,
     129                 :             :                                                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
     130                 :             :                                                          errmsg("SET LOCAL TRANSACTION SNAPSHOT is not implemented")));
     131                 :             : 
     132                 :           0 :                                 WarnNoTransactionBlock(isTopLevel, "SET TRANSACTION");
     133                 :           0 :                                 ImportSnapshot(strVal(&con->val));
     134                 :           0 :                         }
     135                 :             :                         else
     136   [ #  #  #  # ]:           0 :                                 elog(ERROR, "unexpected SET MULTI element: %s",
     137                 :             :                                          stmt->name);
     138                 :          19 :                         break;
     139                 :             :                 case VAR_SET_DEFAULT:
     140         [ +  - ]:          25 :                         if (stmt->is_local)
     141                 :           0 :                                 WarnNoTransactionBlock(isTopLevel, "SET LOCAL");
     142                 :             :                         /* fall through */
     143                 :             :                 case VAR_RESET:
     144                 :        1418 :                         (void) set_config_option(stmt->name,
     145                 :             :                                                                          NULL,
     146                 :         709 :                                                                          (superuser() ? PGC_SUSET : PGC_USERSET),
     147                 :             :                                                                          PGC_S_SESSION,
     148                 :         709 :                                                                          action, true, 0, false);
     149                 :         709 :                         break;
     150                 :             :                 case VAR_RESET_ALL:
     151                 :           0 :                         ResetAllOptions();
     152                 :           0 :                         break;
     153                 :             :         }
     154                 :             : 
     155                 :             :         /* Invoke the post-alter hook for setting this GUC variable, by name. */
     156         [ +  - ]:        4435 :         InvokeObjectPostAlterHookArgStr(ParameterAclRelationId, stmt->name,
     157                 :             :                                                                         ACL_SET, stmt->kind, false);
     158                 :        4357 : }
     159                 :             : 
     160                 :             : /*
     161                 :             :  * Get the value to assign for a VariableSetStmt, or NULL if it's RESET.
     162                 :             :  * The result is palloc'd.
     163                 :             :  *
     164                 :             :  * This is exported for use by actions such as ALTER ROLE SET.
     165                 :             :  */
     166                 :             : char *
     167                 :        3698 : ExtractSetVariableArgs(VariableSetStmt *stmt)
     168                 :             : {
     169      [ -  -  + ]:        3698 :         switch (stmt->kind)
     170                 :             :         {
     171                 :             :                 case VAR_SET_VALUE:
     172                 :        3698 :                         return flatten_set_variable_args(stmt->name, stmt->args);
     173                 :             :                 case VAR_SET_CURRENT:
     174                 :           0 :                         return GetConfigOptionByName(stmt->name, NULL, false);
     175                 :             :                 default:
     176                 :           0 :                         return NULL;
     177                 :             :         }
     178                 :        3698 : }
     179                 :             : 
     180                 :             : /*
     181                 :             :  * flatten_set_variable_args
     182                 :             :  *              Given a parsenode List as emitted by the grammar for SET,
     183                 :             :  *              convert to the flat string representation used by GUC.
     184                 :             :  *
     185                 :             :  * We need to be told the name of the variable the args are for, because
     186                 :             :  * the flattening rules vary (ugh).
     187                 :             :  *
     188                 :             :  * The result is NULL if args is NIL (i.e., SET ... TO DEFAULT), otherwise
     189                 :             :  * a palloc'd string.
     190                 :             :  */
     191                 :             : static char *
     192                 :        3776 : flatten_set_variable_args(const char *name, List *args)
     193                 :             : {
     194                 :        3776 :         struct config_generic *record;
     195                 :        3776 :         int                     flags;
     196                 :        3776 :         StringInfoData buf;
     197                 :        3776 :         ListCell   *l;
     198                 :             : 
     199                 :             :         /* Fast path if just DEFAULT */
     200         [ +  + ]:        3776 :         if (args == NIL)
     201                 :           1 :                 return NULL;
     202                 :             : 
     203                 :             :         /*
     204                 :             :          * Get flags for the variable; if it's not known, use default flags.
     205                 :             :          * (Caller might throw error later, but not our business to do so here.)
     206                 :             :          */
     207                 :        3775 :         record = find_option(name, false, true, WARNING);
     208         [ +  + ]:        3775 :         if (record)
     209                 :        3767 :                 flags = record->flags;
     210                 :             :         else
     211                 :           8 :                 flags = 0;
     212                 :             : 
     213                 :             :         /*
     214                 :             :          * Handle special cases for list input.
     215                 :             :          */
     216         [ +  + ]:        3775 :         if (flags & GUC_LIST_INPUT)
     217                 :             :         {
     218                 :             :                 /* NULL represents an empty list. */
     219         [ +  + ]:         118 :                 if (list_length(args) == 1)
     220                 :             :                 {
     221                 :          82 :                         Node       *arg = (Node *) linitial(args);
     222                 :             : 
     223   [ +  -  +  + ]:          82 :                         if (IsA(arg, A_Const) &&
     224                 :          82 :                                 ((A_Const *) arg)->isnull)
     225                 :           2 :                                 return pstrdup("");
     226         [ +  + ]:          82 :                 }
     227                 :         116 :         }
     228                 :             :         else
     229                 :             :         {
     230                 :             :                 /* Complain if list input and non-list variable. */
     231         [ +  - ]:        3657 :                 if (list_length(args) != 1)
     232   [ #  #  #  # ]:           0 :                         ereport(ERROR,
     233                 :             :                                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     234                 :             :                                          errmsg("SET %s takes only one argument", name)));
     235                 :             :         }
     236                 :             : 
     237                 :        3773 :         initStringInfo(&buf);
     238                 :             : 
     239                 :             :         /*
     240                 :             :          * Each list member may be a plain A_Const node, or an A_Const within a
     241                 :             :          * TypeCast; the latter case is supported only for ConstInterval arguments
     242                 :             :          * (for SET TIME ZONE).
     243                 :             :          */
     244   [ +  -  +  +  :        7592 :         foreach(l, args)
                   +  + ]
     245                 :             :         {
     246                 :        3820 :                 Node       *arg = (Node *) lfirst(l);
     247                 :        3820 :                 char       *val;
     248                 :        3820 :                 TypeName   *typeName = NULL;
     249                 :        3820 :                 A_Const    *con;
     250                 :             : 
     251         [ +  + ]:        3820 :                 if (l != list_head(args))
     252                 :          47 :                         appendStringInfoString(&buf, ", ");
     253                 :             : 
     254         [ +  - ]:        3820 :                 if (IsA(arg, TypeCast))
     255                 :             :                 {
     256                 :           0 :                         TypeCast   *tc = (TypeCast *) arg;
     257                 :             : 
     258                 :           0 :                         arg = tc->arg;
     259                 :           0 :                         typeName = tc->typeName;
     260                 :           0 :                 }
     261                 :             : 
     262         [ +  - ]:        3820 :                 if (!IsA(arg, A_Const))
     263   [ #  #  #  # ]:           0 :                         elog(ERROR, "unrecognized node type: %d", (int) nodeTag(arg));
     264                 :        3820 :                 con = (A_Const *) arg;
     265                 :             : 
     266                 :             :                 /* Complain if NULL is used with a non-list variable. */
     267         [ +  + ]:        3820 :                 if (con->isnull)
     268   [ +  -  +  - ]:           1 :                         ereport(ERROR,
     269                 :             :                                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     270                 :             :                                          errmsg("NULL is an invalid value for %s", name)));
     271                 :             : 
     272   [ +  +  +  - ]:        3819 :                 switch (nodeTag(&con->val))
     273                 :             :                 {
     274                 :             :                         case T_Integer:
     275                 :        2012 :                                 appendStringInfo(&buf, "%d", intVal(&con->val));
     276                 :        2012 :                                 break;
     277                 :             :                         case T_Float:
     278                 :             :                                 /* represented as a string, so just copy it */
     279                 :          25 :                                 appendStringInfoString(&buf, castNode(Float, &con->val)->fval);
     280                 :          25 :                                 break;
     281                 :             :                         case T_String:
     282                 :        1782 :                                 val = strVal(&con->val);
     283         [ -  + ]:        1782 :                                 if (typeName != NULL)
     284                 :             :                                 {
     285                 :             :                                         /*
     286                 :             :                                          * Must be a ConstInterval argument for TIME ZONE. Coerce
     287                 :             :                                          * to interval and back to normalize the value and account
     288                 :             :                                          * for any typmod.
     289                 :             :                                          */
     290                 :           0 :                                         Oid                     typoid;
     291                 :           0 :                                         int32           typmod;
     292                 :           0 :                                         Datum           interval;
     293                 :           0 :                                         char       *intervalout;
     294                 :             : 
     295                 :             :                                         /* gram.y ensures this is only reachable for TIME ZONE */
     296         [ #  # ]:           0 :                                         Assert(!(flags & GUC_LIST_QUOTE));
     297                 :             : 
     298                 :           0 :                                         typenameTypeIdAndMod(NULL, typeName, &typoid, &typmod);
     299         [ #  # ]:           0 :                                         Assert(typoid == INTERVALOID);
     300                 :             : 
     301                 :           0 :                                         interval =
     302                 :           0 :                                                 DirectFunctionCall3(interval_in,
     303                 :             :                                                                                         CStringGetDatum(val),
     304                 :             :                                                                                         ObjectIdGetDatum(InvalidOid),
     305                 :             :                                                                                         Int32GetDatum(typmod));
     306                 :             : 
     307                 :           0 :                                         intervalout =
     308                 :           0 :                                                 DatumGetCString(DirectFunctionCall1(interval_out,
     309                 :             :                                                                                                                         interval));
     310                 :           0 :                                         appendStringInfo(&buf, "INTERVAL '%s'", intervalout);
     311                 :           0 :                                 }
     312                 :             :                                 else
     313                 :             :                                 {
     314                 :             :                                         /*
     315                 :             :                                          * Plain string literal or identifier.  For quote mode,
     316                 :             :                                          * quote it if it's not a vanilla identifier.
     317                 :             :                                          */
     318         [ +  + ]:        1782 :                                         if (flags & GUC_LIST_QUOTE)
     319                 :         111 :                                                 appendStringInfoString(&buf, quote_identifier(val));
     320                 :             :                                         else
     321                 :        1671 :                                                 appendStringInfoString(&buf, val);
     322                 :             :                                 }
     323                 :        1782 :                                 break;
     324                 :             :                         default:
     325   [ #  #  #  # ]:           0 :                                 elog(ERROR, "unrecognized node type: %d",
     326                 :             :                                          (int) nodeTag(&con->val));
     327                 :           0 :                                 break;
     328                 :             :                 }
     329                 :        3819 :         }
     330                 :             : 
     331                 :        3772 :         return buf.data;
     332                 :        3775 : }
     333                 :             : 
     334                 :             : /*
     335                 :             :  * SetPGVariable - SET command exported as an easily-C-callable function.
     336                 :             :  *
     337                 :             :  * This provides access to SET TO value, as well as SET TO DEFAULT (expressed
     338                 :             :  * by passing args == NIL), but not SET FROM CURRENT functionality.
     339                 :             :  */
     340                 :             : void
     341                 :          78 : SetPGVariable(const char *name, List *args, bool is_local)
     342                 :             : {
     343                 :          78 :         char       *argstring = flatten_set_variable_args(name, args);
     344                 :             : 
     345                 :             :         /* Note SET DEFAULT (argstring == NULL) is equivalent to RESET */
     346                 :         156 :         (void) set_config_option(name,
     347                 :          78 :                                                          argstring,
     348                 :          78 :                                                          (superuser() ? PGC_SUSET : PGC_USERSET),
     349                 :             :                                                          PGC_S_SESSION,
     350                 :          78 :                                                          is_local ? GUC_ACTION_LOCAL : GUC_ACTION_SET,
     351                 :             :                                                          true, 0, false);
     352                 :          78 : }
     353                 :             : 
     354                 :             : /*
     355                 :             :  * SET command wrapped as a SQL callable function.
     356                 :             :  */
     357                 :             : Datum
     358                 :          13 : set_config_by_name(PG_FUNCTION_ARGS)
     359                 :             : {
     360                 :          13 :         char       *name;
     361                 :          13 :         char       *value;
     362                 :          13 :         char       *new_value;
     363                 :          13 :         bool            is_local;
     364                 :             : 
     365         [ +  - ]:          13 :         if (PG_ARGISNULL(0))
     366   [ #  #  #  # ]:           0 :                 ereport(ERROR,
     367                 :             :                                 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
     368                 :             :                                  errmsg("SET requires parameter name")));
     369                 :             : 
     370                 :             :         /* Get the GUC variable name */
     371                 :          13 :         name = TextDatumGetCString(PG_GETARG_DATUM(0));
     372                 :             : 
     373                 :             :         /* Get the desired value or set to NULL for a reset request */
     374         [ -  + ]:          13 :         if (PG_ARGISNULL(1))
     375                 :           0 :                 value = NULL;
     376                 :             :         else
     377                 :          13 :                 value = TextDatumGetCString(PG_GETARG_DATUM(1));
     378                 :             : 
     379                 :             :         /*
     380                 :             :          * Get the desired state of is_local. Default to false if provided value
     381                 :             :          * is NULL
     382                 :             :          */
     383         [ -  + ]:          13 :         if (PG_ARGISNULL(2))
     384                 :           0 :                 is_local = false;
     385                 :             :         else
     386                 :          13 :                 is_local = PG_GETARG_BOOL(2);
     387                 :             : 
     388                 :             :         /* Note SET DEFAULT (argstring == NULL) is equivalent to RESET */
     389                 :          26 :         (void) set_config_option(name,
     390                 :          13 :                                                          value,
     391                 :          13 :                                                          (superuser() ? PGC_SUSET : PGC_USERSET),
     392                 :             :                                                          PGC_S_SESSION,
     393                 :          13 :                                                          is_local ? GUC_ACTION_LOCAL : GUC_ACTION_SET,
     394                 :             :                                                          true, 0, false);
     395                 :             : 
     396                 :             :         /* get the new current value */
     397                 :          13 :         new_value = GetConfigOptionByName(name, NULL, false);
     398                 :             : 
     399                 :             :         /* Convert return string to text */
     400                 :          26 :         PG_RETURN_TEXT_P(cstring_to_text(new_value));
     401                 :          13 : }
     402                 :             : 
     403                 :             : 
     404                 :             : /*
     405                 :             :  * SHOW command
     406                 :             :  */
     407                 :             : void
     408                 :         116 : GetPGVariable(const char *name, DestReceiver *dest)
     409                 :             : {
     410         [ +  - ]:         116 :         if (guc_name_compare(name, "all") == 0)
     411                 :           0 :                 ShowAllGUCConfig(dest);
     412                 :             :         else
     413                 :         116 :                 ShowGUCConfigOption(name, dest);
     414                 :         116 : }
     415                 :             : 
     416                 :             : /*
     417                 :             :  * Get a tuple descriptor for SHOW's result
     418                 :             :  */
     419                 :             : TupleDesc
     420                 :         123 : GetPGVariableResultDesc(const char *name)
     421                 :             : {
     422                 :         123 :         TupleDesc       tupdesc;
     423                 :             : 
     424         [ +  - ]:         123 :         if (guc_name_compare(name, "all") == 0)
     425                 :             :         {
     426                 :             :                 /* need a tuple descriptor representing three TEXT columns */
     427                 :           0 :                 tupdesc = CreateTemplateTupleDesc(3);
     428                 :           0 :                 TupleDescInitEntry(tupdesc, (AttrNumber) 1, "name",
     429                 :             :                                                    TEXTOID, -1, 0);
     430                 :           0 :                 TupleDescInitEntry(tupdesc, (AttrNumber) 2, "setting",
     431                 :             :                                                    TEXTOID, -1, 0);
     432                 :           0 :                 TupleDescInitEntry(tupdesc, (AttrNumber) 3, "description",
     433                 :             :                                                    TEXTOID, -1, 0);
     434                 :           0 :         }
     435                 :             :         else
     436                 :             :         {
     437                 :         123 :                 const char *varname;
     438                 :             : 
     439                 :             :                 /* Get the canonical spelling of name */
     440                 :         123 :                 (void) GetConfigOptionByName(name, &varname, false);
     441                 :             : 
     442                 :             :                 /* need a tuple descriptor representing a single TEXT column */
     443                 :         123 :                 tupdesc = CreateTemplateTupleDesc(1);
     444                 :         123 :                 TupleDescInitEntry(tupdesc, (AttrNumber) 1, varname,
     445                 :             :                                                    TEXTOID, -1, 0);
     446                 :         123 :         }
     447                 :         246 :         return tupdesc;
     448                 :         123 : }
     449                 :             : 
     450                 :             : /*
     451                 :             :  * SHOW one variable
     452                 :             :  */
     453                 :             : static void
     454                 :         116 : ShowGUCConfigOption(const char *name, DestReceiver *dest)
     455                 :             : {
     456                 :         116 :         TupOutputState *tstate;
     457                 :         116 :         TupleDesc       tupdesc;
     458                 :         116 :         const char *varname;
     459                 :         116 :         char       *value;
     460                 :             : 
     461                 :             :         /* Get the value and canonical spelling of name */
     462                 :         116 :         value = GetConfigOptionByName(name, &varname, false);
     463                 :             : 
     464                 :             :         /* need a tuple descriptor representing a single TEXT column */
     465                 :         116 :         tupdesc = CreateTemplateTupleDesc(1);
     466                 :         116 :         TupleDescInitBuiltinEntry(tupdesc, (AttrNumber) 1, varname,
     467                 :             :                                                           TEXTOID, -1, 0);
     468                 :             : 
     469                 :             :         /* prepare for projection of tuples */
     470                 :         116 :         tstate = begin_tup_output_tupdesc(dest, tupdesc, &TTSOpsVirtual);
     471                 :             : 
     472                 :             :         /* Send it */
     473                 :         116 :         do_text_output_oneline(tstate, value);
     474                 :             : 
     475                 :         116 :         end_tup_output(tstate);
     476                 :         116 : }
     477                 :             : 
     478                 :             : /*
     479                 :             :  * SHOW ALL command
     480                 :             :  */
     481                 :             : static void
     482                 :           0 : ShowAllGUCConfig(DestReceiver *dest)
     483                 :             : {
     484                 :           0 :         struct config_generic **guc_vars;
     485                 :           0 :         int                     num_vars;
     486                 :           0 :         TupOutputState *tstate;
     487                 :           0 :         TupleDesc       tupdesc;
     488                 :           0 :         Datum           values[3];
     489                 :           0 :         bool            isnull[3] = {false, false, false};
     490                 :             : 
     491                 :             :         /* collect the variables, in sorted order */
     492                 :           0 :         guc_vars = get_guc_variables(&num_vars);
     493                 :             : 
     494                 :             :         /* need a tuple descriptor representing three TEXT columns */
     495                 :           0 :         tupdesc = CreateTemplateTupleDesc(3);
     496                 :           0 :         TupleDescInitBuiltinEntry(tupdesc, (AttrNumber) 1, "name",
     497                 :             :                                                           TEXTOID, -1, 0);
     498                 :           0 :         TupleDescInitBuiltinEntry(tupdesc, (AttrNumber) 2, "setting",
     499                 :             :                                                           TEXTOID, -1, 0);
     500                 :           0 :         TupleDescInitBuiltinEntry(tupdesc, (AttrNumber) 3, "description",
     501                 :             :                                                           TEXTOID, -1, 0);
     502                 :             : 
     503                 :             :         /* prepare for projection of tuples */
     504                 :           0 :         tstate = begin_tup_output_tupdesc(dest, tupdesc, &TTSOpsVirtual);
     505                 :             : 
     506         [ #  # ]:           0 :         for (int i = 0; i < num_vars; i++)
     507                 :             :         {
     508                 :           0 :                 struct config_generic *conf = guc_vars[i];
     509                 :           0 :                 char       *setting;
     510                 :             : 
     511                 :             :                 /* skip if marked NO_SHOW_ALL */
     512         [ #  # ]:           0 :                 if (conf->flags & GUC_NO_SHOW_ALL)
     513                 :           0 :                         continue;
     514                 :             : 
     515                 :             :                 /* return only options visible to the current user */
     516         [ #  # ]:           0 :                 if (!ConfigOptionIsVisible(conf))
     517                 :           0 :                         continue;
     518                 :             : 
     519                 :             :                 /* assign to the values array */
     520                 :           0 :                 values[0] = PointerGetDatum(cstring_to_text(conf->name));
     521                 :             : 
     522                 :           0 :                 setting = ShowGUCOption(conf, true);
     523         [ #  # ]:           0 :                 if (setting)
     524                 :             :                 {
     525                 :           0 :                         values[1] = PointerGetDatum(cstring_to_text(setting));
     526                 :           0 :                         isnull[1] = false;
     527                 :           0 :                 }
     528                 :             :                 else
     529                 :             :                 {
     530                 :           0 :                         values[1] = PointerGetDatum(NULL);
     531                 :           0 :                         isnull[1] = true;
     532                 :             :                 }
     533                 :             : 
     534         [ #  # ]:           0 :                 if (conf->short_desc)
     535                 :             :                 {
     536                 :           0 :                         values[2] = PointerGetDatum(cstring_to_text(conf->short_desc));
     537                 :           0 :                         isnull[2] = false;
     538                 :           0 :                 }
     539                 :             :                 else
     540                 :             :                 {
     541                 :           0 :                         values[2] = PointerGetDatum(NULL);
     542                 :           0 :                         isnull[2] = true;
     543                 :             :                 }
     544                 :             : 
     545                 :             :                 /* send it to dest */
     546                 :           0 :                 do_tup_output(tstate, values, isnull);
     547                 :             : 
     548                 :             :                 /* clean up */
     549                 :           0 :                 pfree(DatumGetPointer(values[0]));
     550         [ #  # ]:           0 :                 if (setting)
     551                 :             :                 {
     552                 :           0 :                         pfree(setting);
     553                 :           0 :                         pfree(DatumGetPointer(values[1]));
     554                 :           0 :                 }
     555         [ #  # ]:           0 :                 if (conf->short_desc)
     556                 :           0 :                         pfree(DatumGetPointer(values[2]));
     557      [ #  #  # ]:           0 :         }
     558                 :             : 
     559                 :           0 :         end_tup_output(tstate);
     560                 :           0 : }
     561                 :             : 
     562                 :             : /*
     563                 :             :  * Return some of the flags associated to the specified GUC in the shape of
     564                 :             :  * a text array, and NULL if it does not exist.  An empty array is returned
     565                 :             :  * if the GUC exists without any meaningful flags to show.
     566                 :             :  */
     567                 :             : Datum
     568                 :         419 : pg_settings_get_flags(PG_FUNCTION_ARGS)
     569                 :             : {
     570                 :             : #define MAX_GUC_FLAGS   6
     571                 :         419 :         char       *varname = TextDatumGetCString(PG_GETARG_DATUM(0));
     572                 :         419 :         struct config_generic *record;
     573                 :         419 :         int                     cnt = 0;
     574                 :         419 :         Datum           flags[MAX_GUC_FLAGS];
     575                 :         419 :         ArrayType  *a;
     576                 :             : 
     577                 :         419 :         record = find_option(varname, false, true, ERROR);
     578                 :             : 
     579                 :             :         /* return NULL if no such variable */
     580         [ +  + ]:         419 :         if (record == NULL)
     581                 :           1 :                 PG_RETURN_NULL();
     582                 :             : 
     583         [ +  + ]:         418 :         if (record->flags & GUC_EXPLAIN)
     584                 :          63 :                 flags[cnt++] = CStringGetTextDatum("EXPLAIN");
     585         [ +  + ]:         418 :         if (record->flags & GUC_NO_RESET)
     586                 :           3 :                 flags[cnt++] = CStringGetTextDatum("NO_RESET");
     587         [ +  + ]:         418 :         if (record->flags & GUC_NO_RESET_ALL)
     588                 :           3 :                 flags[cnt++] = CStringGetTextDatum("NO_RESET_ALL");
     589         [ +  - ]:         418 :         if (record->flags & GUC_NO_SHOW_ALL)
     590                 :           0 :                 flags[cnt++] = CStringGetTextDatum("NO_SHOW_ALL");
     591         [ +  + ]:         418 :         if (record->flags & GUC_NOT_IN_SAMPLE)
     592                 :          56 :                 flags[cnt++] = CStringGetTextDatum("NOT_IN_SAMPLE");
     593         [ +  + ]:         418 :         if (record->flags & GUC_RUNTIME_COMPUTED)
     594                 :           6 :                 flags[cnt++] = CStringGetTextDatum("RUNTIME_COMPUTED");
     595                 :             : 
     596         [ +  - ]:         418 :         Assert(cnt <= MAX_GUC_FLAGS);
     597                 :             : 
     598                 :             :         /* Returns the record as Datum */
     599                 :         418 :         a = construct_array_builtin(flags, cnt, TEXTOID);
     600                 :         418 :         PG_RETURN_ARRAYTYPE_P(a);
     601                 :         419 : }
     602                 :             : 
     603                 :             : /*
     604                 :             :  * Return whether or not the GUC variable is visible to the current user.
     605                 :             :  */
     606                 :             : bool
     607                 :        3254 : ConfigOptionIsVisible(const struct config_generic *conf)
     608                 :             : {
     609   [ +  +  +  - ]:        3254 :         if ((conf->flags & GUC_SUPERUSER_ONLY) &&
     610                 :         161 :                 !has_privs_of_role(GetUserId(), ROLE_PG_READ_ALL_SETTINGS))
     611                 :           0 :                 return false;
     612                 :             :         else
     613                 :        3254 :                 return true;
     614                 :        3254 : }
     615                 :             : 
     616                 :             : /*
     617                 :             :  * Extract fields to show in pg_settings for given variable.
     618                 :             :  */
     619                 :             : static void
     620                 :        2916 : GetConfigOptionValues(const struct config_generic *conf, const char **values)
     621                 :             : {
     622                 :        2916 :         char            buffer[256];
     623                 :             : 
     624                 :             :         /* first get the generic attributes */
     625                 :             : 
     626                 :             :         /* name */
     627                 :        2916 :         values[0] = conf->name;
     628                 :             : 
     629                 :             :         /* setting: use ShowGUCOption in order to avoid duplicating the logic */
     630                 :        2916 :         values[1] = ShowGUCOption(conf, false);
     631                 :             : 
     632                 :             :         /* unit, if any (NULL is fine) */
     633                 :        2916 :         values[2] = get_config_unit_name(conf->flags);
     634                 :             : 
     635                 :             :         /* group */
     636                 :        2916 :         values[3] = _(config_group_names[conf->group]);
     637                 :             : 
     638                 :             :         /* short_desc */
     639         [ +  - ]:        2916 :         values[4] = conf->short_desc != NULL ? _(conf->short_desc) : NULL;
     640                 :             : 
     641                 :             :         /* extra_desc */
     642         [ +  + ]:        2916 :         values[5] = conf->long_desc != NULL ? _(conf->long_desc) : NULL;
     643                 :             : 
     644                 :             :         /* context */
     645                 :        2916 :         values[6] = GucContext_Names[conf->context];
     646                 :             : 
     647                 :             :         /* vartype */
     648                 :        2916 :         values[7] = config_type_names[conf->vartype];
     649                 :             : 
     650                 :             :         /* source */
     651                 :        2916 :         values[8] = GucSource_Names[conf->source];
     652                 :             : 
     653                 :             :         /* now get the type specific attributes */
     654   [ +  +  +  -  :        2916 :         switch (conf->vartype)
                   +  + ]
     655                 :             :         {
     656                 :             :                 case PGC_BOOL:
     657                 :             :                         {
     658                 :         871 :                                 const struct config_bool *lconf = &conf->_bool;
     659                 :             : 
     660                 :             :                                 /* min_val */
     661                 :         871 :                                 values[9] = NULL;
     662                 :             : 
     663                 :             :                                 /* max_val */
     664                 :         871 :                                 values[10] = NULL;
     665                 :             : 
     666                 :             :                                 /* enumvals */
     667                 :         871 :                                 values[11] = NULL;
     668                 :             : 
     669                 :             :                                 /* boot_val */
     670                 :         871 :                                 values[12] = pstrdup(lconf->boot_val ? "on" : "off");
     671                 :             : 
     672                 :             :                                 /* reset_val */
     673                 :         871 :                                 values[13] = pstrdup(lconf->reset_val ? "on" : "off");
     674                 :         871 :                         }
     675                 :         871 :                         break;
     676                 :             : 
     677                 :             :                 case PGC_INT:
     678                 :             :                         {
     679                 :        1043 :                                 const struct config_int *lconf = &conf->_int;
     680                 :             : 
     681                 :             :                                 /* min_val */
     682                 :        1043 :                                 snprintf(buffer, sizeof(buffer), "%d", lconf->min);
     683                 :        1043 :                                 values[9] = pstrdup(buffer);
     684                 :             : 
     685                 :             :                                 /* max_val */
     686                 :        1043 :                                 snprintf(buffer, sizeof(buffer), "%d", lconf->max);
     687                 :        1043 :                                 values[10] = pstrdup(buffer);
     688                 :             : 
     689                 :             :                                 /* enumvals */
     690                 :        1043 :                                 values[11] = NULL;
     691                 :             : 
     692                 :             :                                 /* boot_val */
     693                 :        1043 :                                 snprintf(buffer, sizeof(buffer), "%d", lconf->boot_val);
     694                 :        1043 :                                 values[12] = pstrdup(buffer);
     695                 :             : 
     696                 :             :                                 /* reset_val */
     697                 :        1043 :                                 snprintf(buffer, sizeof(buffer), "%d", lconf->reset_val);
     698                 :        1043 :                                 values[13] = pstrdup(buffer);
     699                 :        1043 :                         }
     700                 :        1043 :                         break;
     701                 :             : 
     702                 :             :                 case PGC_REAL:
     703                 :             :                         {
     704                 :         182 :                                 const struct config_real *lconf = &conf->_real;
     705                 :             : 
     706                 :             :                                 /* min_val */
     707                 :         182 :                                 snprintf(buffer, sizeof(buffer), "%g", lconf->min);
     708                 :         182 :                                 values[9] = pstrdup(buffer);
     709                 :             : 
     710                 :             :                                 /* max_val */
     711                 :         182 :                                 snprintf(buffer, sizeof(buffer), "%g", lconf->max);
     712                 :         182 :                                 values[10] = pstrdup(buffer);
     713                 :             : 
     714                 :             :                                 /* enumvals */
     715                 :         182 :                                 values[11] = NULL;
     716                 :             : 
     717                 :             :                                 /* boot_val */
     718                 :         182 :                                 snprintf(buffer, sizeof(buffer), "%g", lconf->boot_val);
     719                 :         182 :                                 values[12] = pstrdup(buffer);
     720                 :             : 
     721                 :             :                                 /* reset_val */
     722                 :         182 :                                 snprintf(buffer, sizeof(buffer), "%g", lconf->reset_val);
     723                 :         182 :                                 values[13] = pstrdup(buffer);
     724                 :         182 :                         }
     725                 :         182 :                         break;
     726                 :             : 
     727                 :             :                 case PGC_STRING:
     728                 :             :                         {
     729                 :         528 :                                 const struct config_string *lconf = &conf->_string;
     730                 :             : 
     731                 :             :                                 /* min_val */
     732                 :         528 :                                 values[9] = NULL;
     733                 :             : 
     734                 :             :                                 /* max_val */
     735                 :         528 :                                 values[10] = NULL;
     736                 :             : 
     737                 :             :                                 /* enumvals */
     738                 :         528 :                                 values[11] = NULL;
     739                 :             : 
     740                 :             :                                 /* boot_val */
     741         [ +  + ]:         528 :                                 if (lconf->boot_val == NULL)
     742                 :          49 :                                         values[12] = NULL;
     743                 :             :                                 else
     744                 :         479 :                                         values[12] = pstrdup(lconf->boot_val);
     745                 :             : 
     746                 :             :                                 /* reset_val */
     747         [ +  + ]:         528 :                                 if (lconf->reset_val == NULL)
     748                 :           7 :                                         values[13] = NULL;
     749                 :             :                                 else
     750                 :         521 :                                         values[13] = pstrdup(lconf->reset_val);
     751                 :         528 :                         }
     752                 :         528 :                         break;
     753                 :             : 
     754                 :             :                 case PGC_ENUM:
     755                 :             :                         {
     756                 :         292 :                                 const struct config_enum *lconf = &conf->_enum;
     757                 :             : 
     758                 :             :                                 /* min_val */
     759                 :         292 :                                 values[9] = NULL;
     760                 :             : 
     761                 :             :                                 /* max_val */
     762                 :         292 :                                 values[10] = NULL;
     763                 :             : 
     764                 :             :                                 /* enumvals */
     765                 :             : 
     766                 :             :                                 /*
     767                 :             :                                  * NOTE! enumvals with double quotes in them are not
     768                 :             :                                  * supported!
     769                 :             :                                  */
     770                 :         292 :                                 values[11] = config_enum_get_options(lconf,
     771                 :             :                                                                                                          "{\"", "\"}", "\",\"");
     772                 :             : 
     773                 :             :                                 /* boot_val */
     774                 :         584 :                                 values[12] = pstrdup(config_enum_lookup_by_value(conf,
     775                 :         292 :                                                                                                                                  lconf->boot_val));
     776                 :             : 
     777                 :             :                                 /* reset_val */
     778                 :         584 :                                 values[13] = pstrdup(config_enum_lookup_by_value(conf,
     779                 :         292 :                                                                                                                                  lconf->reset_val));
     780                 :         292 :                         }
     781                 :         292 :                         break;
     782                 :             : 
     783                 :             :                 default:
     784                 :             :                         {
     785                 :             :                                 /*
     786                 :             :                                  * should never get here, but in case we do, set 'em to NULL
     787                 :             :                                  */
     788                 :             : 
     789                 :             :                                 /* min_val */
     790                 :           0 :                                 values[9] = NULL;
     791                 :             : 
     792                 :             :                                 /* max_val */
     793                 :           0 :                                 values[10] = NULL;
     794                 :             : 
     795                 :             :                                 /* enumvals */
     796                 :           0 :                                 values[11] = NULL;
     797                 :             : 
     798                 :             :                                 /* boot_val */
     799                 :           0 :                                 values[12] = NULL;
     800                 :             : 
     801                 :             :                                 /* reset_val */
     802                 :           0 :                                 values[13] = NULL;
     803                 :             :                         }
     804                 :           0 :                         break;
     805                 :             :         }
     806                 :             : 
     807                 :             :         /*
     808                 :             :          * If the setting came from a config file, set the source location. For
     809                 :             :          * security reasons, we don't show source file/line number for
     810                 :             :          * insufficiently-privileged users.
     811                 :             :          */
     812   [ +  +  -  + ]:        2916 :         if (conf->source == PGC_S_FILE &&
     813                 :         168 :                 has_privs_of_role(GetUserId(), ROLE_PG_READ_ALL_SETTINGS))
     814                 :             :         {
     815                 :         168 :                 values[14] = conf->sourcefile;
     816                 :         168 :                 snprintf(buffer, sizeof(buffer), "%d", conf->sourceline);
     817                 :         168 :                 values[15] = pstrdup(buffer);
     818                 :         168 :         }
     819                 :             :         else
     820                 :             :         {
     821                 :        2748 :                 values[14] = NULL;
     822                 :        2748 :                 values[15] = NULL;
     823                 :             :         }
     824                 :             : 
     825                 :        2916 :         values[16] = (conf->status & GUC_PENDING_RESTART) ? "t" : "f";
     826                 :        2916 : }
     827                 :             : 
     828                 :             : /*
     829                 :             :  * show_config_by_name - equiv to SHOW X command but implemented as
     830                 :             :  * a function.
     831                 :             :  */
     832                 :             : Datum
     833                 :          81 : show_config_by_name(PG_FUNCTION_ARGS)
     834                 :             : {
     835                 :          81 :         char       *varname = TextDatumGetCString(PG_GETARG_DATUM(0));
     836                 :          81 :         char       *varval;
     837                 :             : 
     838                 :             :         /* Get the value */
     839                 :          81 :         varval = GetConfigOptionByName(varname, NULL, false);
     840                 :             : 
     841                 :             :         /* Convert to text */
     842                 :         162 :         PG_RETURN_TEXT_P(cstring_to_text(varval));
     843                 :          81 : }
     844                 :             : 
     845                 :             : /*
     846                 :             :  * show_config_by_name_missing_ok - equiv to SHOW X command but implemented as
     847                 :             :  * a function.  If X does not exist, suppress the error and just return NULL
     848                 :             :  * if missing_ok is true.
     849                 :             :  */
     850                 :             : Datum
     851                 :           3 : show_config_by_name_missing_ok(PG_FUNCTION_ARGS)
     852                 :             : {
     853                 :           3 :         char       *varname = TextDatumGetCString(PG_GETARG_DATUM(0));
     854                 :           3 :         bool            missing_ok = PG_GETARG_BOOL(1);
     855                 :           3 :         char       *varval;
     856                 :             : 
     857                 :             :         /* Get the value */
     858                 :           3 :         varval = GetConfigOptionByName(varname, NULL, missing_ok);
     859                 :             : 
     860                 :             :         /* return NULL if no such variable */
     861         [ +  + ]:           3 :         if (varval == NULL)
     862                 :           1 :                 PG_RETURN_NULL();
     863                 :             : 
     864                 :             :         /* Convert to text */
     865                 :           2 :         PG_RETURN_TEXT_P(cstring_to_text(varval));
     866                 :           3 : }
     867                 :             : 
     868                 :             : /*
     869                 :             :  * show_all_settings - equiv to SHOW ALL command but implemented as
     870                 :             :  * a Table Function.
     871                 :             :  */
     872                 :             : #define NUM_PG_SETTINGS_ATTS    17
     873                 :             : 
     874                 :             : Datum
     875                 :        2923 : show_all_settings(PG_FUNCTION_ARGS)
     876                 :             : {
     877                 :        2923 :         FuncCallContext *funcctx;
     878                 :        2923 :         struct config_generic **guc_vars;
     879                 :        2923 :         int                     num_vars;
     880                 :        2923 :         TupleDesc       tupdesc;
     881                 :        2923 :         int                     call_cntr;
     882                 :        2923 :         int                     max_calls;
     883                 :        2923 :         AttInMetadata *attinmeta;
     884                 :        2923 :         MemoryContext oldcontext;
     885                 :             : 
     886                 :             :         /* stuff done only on the first call of the function */
     887         [ +  + ]:        2923 :         if (SRF_IS_FIRSTCALL())
     888                 :             :         {
     889                 :             :                 /* create a function context for cross-call persistence */
     890                 :           7 :                 funcctx = SRF_FIRSTCALL_INIT();
     891                 :             : 
     892                 :             :                 /*
     893                 :             :                  * switch to memory context appropriate for multiple function calls
     894                 :             :                  */
     895                 :           7 :                 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
     896                 :             : 
     897                 :             :                 /*
     898                 :             :                  * need a tuple descriptor representing NUM_PG_SETTINGS_ATTS columns
     899                 :             :                  * of the appropriate types
     900                 :             :                  */
     901                 :           7 :                 tupdesc = CreateTemplateTupleDesc(NUM_PG_SETTINGS_ATTS);
     902                 :           7 :                 TupleDescInitEntry(tupdesc, (AttrNumber) 1, "name",
     903                 :             :                                                    TEXTOID, -1, 0);
     904                 :           7 :                 TupleDescInitEntry(tupdesc, (AttrNumber) 2, "setting",
     905                 :             :                                                    TEXTOID, -1, 0);
     906                 :           7 :                 TupleDescInitEntry(tupdesc, (AttrNumber) 3, "unit",
     907                 :             :                                                    TEXTOID, -1, 0);
     908                 :           7 :                 TupleDescInitEntry(tupdesc, (AttrNumber) 4, "category",
     909                 :             :                                                    TEXTOID, -1, 0);
     910                 :           7 :                 TupleDescInitEntry(tupdesc, (AttrNumber) 5, "short_desc",
     911                 :             :                                                    TEXTOID, -1, 0);
     912                 :           7 :                 TupleDescInitEntry(tupdesc, (AttrNumber) 6, "extra_desc",
     913                 :             :                                                    TEXTOID, -1, 0);
     914                 :           7 :                 TupleDescInitEntry(tupdesc, (AttrNumber) 7, "context",
     915                 :             :                                                    TEXTOID, -1, 0);
     916                 :           7 :                 TupleDescInitEntry(tupdesc, (AttrNumber) 8, "vartype",
     917                 :             :                                                    TEXTOID, -1, 0);
     918                 :           7 :                 TupleDescInitEntry(tupdesc, (AttrNumber) 9, "source",
     919                 :             :                                                    TEXTOID, -1, 0);
     920                 :           7 :                 TupleDescInitEntry(tupdesc, (AttrNumber) 10, "min_val",
     921                 :             :                                                    TEXTOID, -1, 0);
     922                 :           7 :                 TupleDescInitEntry(tupdesc, (AttrNumber) 11, "max_val",
     923                 :             :                                                    TEXTOID, -1, 0);
     924                 :           7 :                 TupleDescInitEntry(tupdesc, (AttrNumber) 12, "enumvals",
     925                 :             :                                                    TEXTARRAYOID, -1, 0);
     926                 :           7 :                 TupleDescInitEntry(tupdesc, (AttrNumber) 13, "boot_val",
     927                 :             :                                                    TEXTOID, -1, 0);
     928                 :           7 :                 TupleDescInitEntry(tupdesc, (AttrNumber) 14, "reset_val",
     929                 :             :                                                    TEXTOID, -1, 0);
     930                 :           7 :                 TupleDescInitEntry(tupdesc, (AttrNumber) 15, "sourcefile",
     931                 :             :                                                    TEXTOID, -1, 0);
     932                 :           7 :                 TupleDescInitEntry(tupdesc, (AttrNumber) 16, "sourceline",
     933                 :             :                                                    INT4OID, -1, 0);
     934                 :           7 :                 TupleDescInitEntry(tupdesc, (AttrNumber) 17, "pending_restart",
     935                 :             :                                                    BOOLOID, -1, 0);
     936                 :             : 
     937                 :             :                 /*
     938                 :             :                  * Generate attribute metadata needed later to produce tuples from raw
     939                 :             :                  * C strings
     940                 :             :                  */
     941                 :           7 :                 attinmeta = TupleDescGetAttInMetadata(tupdesc);
     942                 :           7 :                 funcctx->attinmeta = attinmeta;
     943                 :             : 
     944                 :             :                 /* collect the variables, in sorted order */
     945                 :           7 :                 guc_vars = get_guc_variables(&num_vars);
     946                 :             : 
     947                 :             :                 /* use user_fctx to remember the array location */
     948                 :           7 :                 funcctx->user_fctx = guc_vars;
     949                 :             : 
     950                 :             :                 /* total number of tuples to be returned */
     951                 :           7 :                 funcctx->max_calls = num_vars;
     952                 :             : 
     953                 :           7 :                 MemoryContextSwitchTo(oldcontext);
     954                 :           7 :         }
     955                 :             : 
     956                 :             :         /* stuff done on every call of the function */
     957                 :        2923 :         funcctx = SRF_PERCALL_SETUP();
     958                 :             : 
     959                 :        2923 :         guc_vars = (struct config_generic **) funcctx->user_fctx;
     960                 :        2923 :         call_cntr = funcctx->call_cntr;
     961                 :        2923 :         max_calls = funcctx->max_calls;
     962                 :        2923 :         attinmeta = funcctx->attinmeta;
     963                 :             : 
     964         [ +  + ]:        2968 :         while (call_cntr < max_calls)        /* do when there is more left to send */
     965                 :             :         {
     966                 :        2961 :                 struct config_generic *conf = guc_vars[call_cntr];
     967                 :        2961 :                 char       *values[NUM_PG_SETTINGS_ATTS];
     968                 :        2961 :                 HeapTuple       tuple;
     969                 :        2961 :                 Datum           result;
     970                 :             : 
     971                 :             :                 /* skip if marked NO_SHOW_ALL or if not visible to current user */
     972   [ +  +  -  + ]:        2961 :                 if ((conf->flags & GUC_NO_SHOW_ALL) ||
     973                 :        2916 :                         !ConfigOptionIsVisible(conf))
     974                 :             :                 {
     975                 :          45 :                         call_cntr = ++funcctx->call_cntr;
     976                 :          45 :                         continue;
     977                 :             :                 }
     978                 :             : 
     979                 :             :                 /* extract values for the current variable */
     980                 :        2916 :                 GetConfigOptionValues(conf, (const char **) values);
     981                 :             : 
     982                 :             :                 /* build a tuple */
     983                 :        2916 :                 tuple = BuildTupleFromCStrings(attinmeta, values);
     984                 :             : 
     985                 :             :                 /* make the tuple into a datum */
     986                 :        2916 :                 result = HeapTupleGetDatum(tuple);
     987                 :             : 
     988                 :        2916 :                 SRF_RETURN_NEXT(funcctx, result);
     989      [ +  +  - ]:        2961 :         }
     990                 :             : 
     991                 :             :         /* do when there is no more left */
     992         [ +  - ]:           7 :         SRF_RETURN_DONE(funcctx);
     993         [ -  + ]:        2923 : }
     994                 :             : 
     995                 :             : /*
     996                 :             :  * show_all_file_settings
     997                 :             :  *
     998                 :             :  * Returns a table of all parameter settings in all configuration files
     999                 :             :  * which includes the config file pathname, the line number, a sequence number
    1000                 :             :  * indicating the order in which the settings were encountered, the parameter
    1001                 :             :  * name and value, a bool showing if the value could be applied, and possibly
    1002                 :             :  * an associated error message.  (For problems such as syntax errors, the
    1003                 :             :  * parameter name/value might be NULL.)
    1004                 :             :  *
    1005                 :             :  * Note: no filtering is done here, instead we depend on the GRANT system
    1006                 :             :  * to prevent unprivileged users from accessing this function or the view
    1007                 :             :  * built on top of it.
    1008                 :             :  */
    1009                 :             : Datum
    1010                 :           1 : show_all_file_settings(PG_FUNCTION_ARGS)
    1011                 :             : {
    1012                 :             : #define NUM_PG_FILE_SETTINGS_ATTS 7
    1013                 :           1 :         ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
    1014                 :           1 :         ConfigVariable *conf;
    1015                 :             : 
    1016                 :             :         /* Scan the config files using current context as workspace */
    1017                 :           1 :         conf = ProcessConfigFileInternal(PGC_SIGHUP, false, DEBUG3);
    1018                 :             : 
    1019                 :             :         /* Build a tuplestore to return our results in */
    1020                 :           1 :         InitMaterializedSRF(fcinfo, 0);
    1021                 :             : 
    1022                 :             :         /* Process the results and create a tuplestore */
    1023         [ +  + ]:          31 :         for (int seqno = 1; conf != NULL; conf = conf->next, seqno++)
    1024                 :             :         {
    1025                 :          30 :                 Datum           values[NUM_PG_FILE_SETTINGS_ATTS];
    1026                 :          30 :                 bool            nulls[NUM_PG_FILE_SETTINGS_ATTS];
    1027                 :             : 
    1028                 :          30 :                 memset(values, 0, sizeof(values));
    1029                 :          30 :                 memset(nulls, 0, sizeof(nulls));
    1030                 :             : 
    1031                 :             :                 /* sourcefile */
    1032         [ +  - ]:          30 :                 if (conf->filename)
    1033                 :          30 :                         values[0] = PointerGetDatum(cstring_to_text(conf->filename));
    1034                 :             :                 else
    1035                 :           0 :                         nulls[0] = true;
    1036                 :             : 
    1037                 :             :                 /* sourceline (not meaningful if no sourcefile) */
    1038         [ +  - ]:          30 :                 if (conf->filename)
    1039                 :          30 :                         values[1] = Int32GetDatum(conf->sourceline);
    1040                 :             :                 else
    1041                 :           0 :                         nulls[1] = true;
    1042                 :             : 
    1043                 :             :                 /* seqno */
    1044                 :          30 :                 values[2] = Int32GetDatum(seqno);
    1045                 :             : 
    1046                 :             :                 /* name */
    1047         [ +  - ]:          30 :                 if (conf->name)
    1048                 :          30 :                         values[3] = PointerGetDatum(cstring_to_text(conf->name));
    1049                 :             :                 else
    1050                 :           0 :                         nulls[3] = true;
    1051                 :             : 
    1052                 :             :                 /* setting */
    1053         [ +  - ]:          30 :                 if (conf->value)
    1054                 :          30 :                         values[4] = PointerGetDatum(cstring_to_text(conf->value));
    1055                 :             :                 else
    1056                 :           0 :                         nulls[4] = true;
    1057                 :             : 
    1058                 :             :                 /* applied */
    1059                 :          30 :                 values[5] = BoolGetDatum(conf->applied);
    1060                 :             : 
    1061                 :             :                 /* error */
    1062         [ -  + ]:          30 :                 if (conf->errmsg)
    1063                 :           0 :                         values[6] = PointerGetDatum(cstring_to_text(conf->errmsg));
    1064                 :             :                 else
    1065                 :          30 :                         nulls[6] = true;
    1066                 :             : 
    1067                 :             :                 /* shove row into tuplestore */
    1068                 :          30 :                 tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
    1069                 :          30 :         }
    1070                 :             : 
    1071                 :           1 :         return (Datum) 0;
    1072                 :           1 : }
        

Generated by: LCOV version 2.3.2-1