LCOV - code coverage report
Current view: top level - src/backend/utils/misc - guc_funcs.c (source / functions) Coverage Total Hit
Test: PostgreSQL 20devel Lines: 88.1 % 386 340
Test Date: 2026-07-26 06:15:43 Functions: 100.0 % 16 16
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 72.6 % 201 146

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

Generated by: LCOV version 2.0-1