mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-12-15 08:20:16 +08:00
Add pg_file_settings view and function
The function and view added here provide a way to look at all settings in postgresql.conf, any #include'd files, and postgresql.auto.conf (which is what backs the ALTER SYSTEM command). The information returned includes the configuration file name, line number in that file, sequence number indicating when the parameter is loaded (useful to see if it is later masked by another definition of the same parameter), parameter name, and what it is set to at that point. This information is updated on reload of the server. This is unfiltered, privileged, information and therefore access is restricted to superusers through the GRANT system. Author: Sawada Masahiko, various improvements by me. Reviewers: David Steele
This commit is contained in:
parent
bab64ef9e8
commit
a97e0c3354
@ -7559,6 +7559,11 @@
|
|||||||
<entry>parameter settings</entry>
|
<entry>parameter settings</entry>
|
||||||
</row>
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry><link linkend="view-pg-file-settings"><structname>pg_file_settings</structname></link></entry>
|
||||||
|
<entry>file location of parameter settings</entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
<row>
|
<row>
|
||||||
<entry><link linkend="view-pg-shadow"><structname>pg_shadow</structname></link></entry>
|
<entry><link linkend="view-pg-shadow"><structname>pg_shadow</structname></link></entry>
|
||||||
<entry>database users</entry>
|
<entry>database users</entry>
|
||||||
@ -9173,6 +9178,79 @@ SELECT * FROM pg_locks pl LEFT JOIN pg_prepared_xacts ppx
|
|||||||
|
|
||||||
</sect1>
|
</sect1>
|
||||||
|
|
||||||
|
<sect1 id="view-pg-file-settings">
|
||||||
|
<title><structname>pg_file_settings</structname></title>
|
||||||
|
|
||||||
|
<indexterm zone="view-pg-file-settings">
|
||||||
|
<primary>pg_file_settings</primary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
The view <structname>pg_file_settings</structname> provides the file
|
||||||
|
name, line number and value of all parameters which are set through
|
||||||
|
configuration files.
|
||||||
|
In contrast to <structname>pg_settings</structname>, a row is provided for
|
||||||
|
each occurrence of the parameter across all configuration files. This is helpful
|
||||||
|
for discovering why one value may have been used in preference to another
|
||||||
|
when the parameters were loaded.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<title><structname>pg_file_settings</> Columns</title>
|
||||||
|
|
||||||
|
<tgroup cols="3">
|
||||||
|
<thead>
|
||||||
|
<row>
|
||||||
|
<entry>Name</entry>
|
||||||
|
<entry>Type</entry>
|
||||||
|
<entry>Description</entry>
|
||||||
|
</row>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<row>
|
||||||
|
<entry><structfield>sourcefile</structfield></entry>
|
||||||
|
<entry><structfield>text</structfield></entry>
|
||||||
|
<entry>Path to and name of the configration file</entry>
|
||||||
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry><structfield>sourceline</structfield></entry>
|
||||||
|
<entry><structfield>integer</structfield></entry>
|
||||||
|
<entry>
|
||||||
|
Line number within the configuration file where the value was set
|
||||||
|
</entry>
|
||||||
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry><structfield>seqno</structfield></entry>
|
||||||
|
<entry><structfield>integer</structfield></entry>
|
||||||
|
<entry>Order in which the setting was loaded</entry>
|
||||||
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry><structfield>name</structfield></entry>
|
||||||
|
<entry><structfield>text</structfield></entry>
|
||||||
|
<entry>Run-time configuration parameter name</entry>
|
||||||
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry><structfield>setting</structfield></entry>
|
||||||
|
<entry><structfield>text</structfield></entry>
|
||||||
|
<entry>value of the parameter</entry>
|
||||||
|
</row>
|
||||||
|
</tbody>
|
||||||
|
</tgroup>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
See <xref linkend="config-setting"> for more information about the various
|
||||||
|
ways to change these parameters.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
The <structname>pg_file_settings</structname> view cannot be modified
|
||||||
|
directly as it represents information, as read in at server start or
|
||||||
|
reload time, about all parameter settings across all configuration files.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
</sect1>
|
||||||
|
|
||||||
<sect1 id="view-pg-shadow">
|
<sect1 id="view-pg-shadow">
|
||||||
<title><structname>pg_shadow</structname></title>
|
<title><structname>pg_shadow</structname></title>
|
||||||
|
|
||||||
|
@ -411,6 +411,12 @@ CREATE RULE pg_settings_n AS
|
|||||||
|
|
||||||
GRANT SELECT, UPDATE ON pg_settings TO PUBLIC;
|
GRANT SELECT, UPDATE ON pg_settings TO PUBLIC;
|
||||||
|
|
||||||
|
CREATE VIEW pg_file_settings AS
|
||||||
|
SELECT * FROM pg_show_all_file_settings() AS A;
|
||||||
|
|
||||||
|
REVOKE ALL on pg_file_settings FROM PUBLIC;
|
||||||
|
REVOKE EXECUTE ON FUNCTION pg_show_all_file_settings() FROM PUBLIC;
|
||||||
|
|
||||||
CREATE VIEW pg_timezone_abbrevs AS
|
CREATE VIEW pg_timezone_abbrevs AS
|
||||||
SELECT * FROM pg_timezone_abbrevs();
|
SELECT * FROM pg_timezone_abbrevs();
|
||||||
|
|
||||||
|
@ -120,6 +120,7 @@ ProcessConfigFile(GucContext context)
|
|||||||
*head,
|
*head,
|
||||||
*tail;
|
*tail;
|
||||||
int i;
|
int i;
|
||||||
|
int file_variables_count = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Config files are processed on startup (by the postmaster only)
|
* Config files are processed on startup (by the postmaster only)
|
||||||
@ -255,6 +256,7 @@ ProcessConfigFile(GucContext context)
|
|||||||
error = true;
|
error = true;
|
||||||
ConfFileWithError = item->filename;
|
ConfFileWithError = item->filename;
|
||||||
}
|
}
|
||||||
|
file_variables_count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -341,6 +343,54 @@ ProcessConfigFile(GucContext context)
|
|||||||
PGC_BACKEND, PGC_S_DYNAMIC_DEFAULT);
|
PGC_BACKEND, PGC_S_DYNAMIC_DEFAULT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check if we have allocated the array yet.
|
||||||
|
*
|
||||||
|
* If not, allocate it based on the number of file variables we have seen.
|
||||||
|
*/
|
||||||
|
if (!guc_file_variables)
|
||||||
|
{
|
||||||
|
/* For the first call */
|
||||||
|
num_guc_file_variables = file_variables_count;
|
||||||
|
guc_file_variables = (ConfigFileVariable *) guc_malloc(FATAL,
|
||||||
|
num_guc_file_variables * sizeof(struct ConfigFileVariable));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Free all of the previously allocated entries */
|
||||||
|
for (i = 0; i < num_guc_file_variables; i++)
|
||||||
|
{
|
||||||
|
free(guc_file_variables[i].name);
|
||||||
|
free(guc_file_variables[i].value);
|
||||||
|
free(guc_file_variables[i].filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update the global count and realloc based on the new size */
|
||||||
|
num_guc_file_variables = file_variables_count;
|
||||||
|
guc_file_variables = (ConfigFileVariable *) guc_realloc(FATAL,
|
||||||
|
guc_file_variables,
|
||||||
|
num_guc_file_variables * sizeof(struct ConfigFileVariable));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copy the settings which came from the files read into the
|
||||||
|
* guc_file_variables array which backs the pg_show_file_settings()
|
||||||
|
* function.
|
||||||
|
*/
|
||||||
|
for (item = head, i = 0; item && i < num_guc_file_variables;
|
||||||
|
item = item->next, i++)
|
||||||
|
{
|
||||||
|
guc_file_variables[i].name = guc_strdup(FATAL, item->name);
|
||||||
|
guc_file_variables[i].value = guc_strdup(FATAL, item->value);
|
||||||
|
guc_file_variables[i].filename = guc_strdup(FATAL, item->filename);
|
||||||
|
guc_file_variables[i].sourceline = item->sourceline;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We had better have made it through the loop above to a clean ending. */
|
||||||
|
Assert(!item && i == num_guc_file_variables);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now apply the values from the config file.
|
* Now apply the values from the config file.
|
||||||
*/
|
*/
|
||||||
|
@ -3678,6 +3678,22 @@ static struct config_generic **guc_variables;
|
|||||||
/* Current number of variables contained in the vector */
|
/* Current number of variables contained in the vector */
|
||||||
static int num_guc_variables;
|
static int num_guc_variables;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Lookup of variables for pg_file_settings view.
|
||||||
|
* guc_file_variables is an array of length num_guc_file_variables.
|
||||||
|
*/
|
||||||
|
typedef struct ConfigFileVariable
|
||||||
|
{
|
||||||
|
char *name;
|
||||||
|
char *value;
|
||||||
|
char *filename;
|
||||||
|
int sourceline;
|
||||||
|
} ConfigFileVariable;
|
||||||
|
static struct ConfigFileVariable *guc_file_variables;
|
||||||
|
|
||||||
|
/* Number of file variables */
|
||||||
|
static int num_guc_file_variables;
|
||||||
|
|
||||||
/* Vector capacity */
|
/* Vector capacity */
|
||||||
static int size_guc_variables;
|
static int size_guc_variables;
|
||||||
|
|
||||||
@ -8148,6 +8164,110 @@ show_all_settings(PG_FUNCTION_ARGS)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* show_all_file_settings
|
||||||
|
*
|
||||||
|
* returns a table of all parameter settings in all configuration files
|
||||||
|
* which includes the config file path/name, filename, a sequence number
|
||||||
|
* indicating when we loaded it, the parameter name, and the value it is
|
||||||
|
* set to.
|
||||||
|
*
|
||||||
|
* Note: no filtering is done here, instead we depend on the GRANT system
|
||||||
|
* to prevent unprivileged users from accessing this function or the view
|
||||||
|
* built on top of it.
|
||||||
|
*/
|
||||||
|
Datum
|
||||||
|
show_all_file_settings(PG_FUNCTION_ARGS)
|
||||||
|
{
|
||||||
|
#define NUM_PG_FILE_SETTINGS_ATTS 5
|
||||||
|
FuncCallContext *funcctx;
|
||||||
|
TupleDesc tupdesc;
|
||||||
|
int call_cntr;
|
||||||
|
int max_calls;
|
||||||
|
AttInMetadata *attinmeta;
|
||||||
|
MemoryContext oldcontext;
|
||||||
|
|
||||||
|
if (SRF_IS_FIRSTCALL())
|
||||||
|
{
|
||||||
|
funcctx = SRF_FIRSTCALL_INIT();
|
||||||
|
|
||||||
|
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* need a tuple descriptor representing NUM_PG_SETTINGS_ATTS columns
|
||||||
|
* of the appropriate types
|
||||||
|
*/
|
||||||
|
|
||||||
|
tupdesc = CreateTemplateTupleDesc(NUM_PG_FILE_SETTINGS_ATTS, false);
|
||||||
|
TupleDescInitEntry(tupdesc, (AttrNumber) 1, "sourcefile",
|
||||||
|
TEXTOID, -1, 0);
|
||||||
|
TupleDescInitEntry(tupdesc, (AttrNumber) 2, "sourceline",
|
||||||
|
INT4OID, -1, 0);
|
||||||
|
TupleDescInitEntry(tupdesc, (AttrNumber) 3, "seqno",
|
||||||
|
INT4OID, -1, 0);
|
||||||
|
TupleDescInitEntry(tupdesc, (AttrNumber) 4, "name",
|
||||||
|
TEXTOID, -1, 0);
|
||||||
|
TupleDescInitEntry(tupdesc, (AttrNumber) 5, "setting",
|
||||||
|
TEXTOID, -1, 0);
|
||||||
|
|
||||||
|
attinmeta = TupleDescGetAttInMetadata(tupdesc);
|
||||||
|
funcctx->attinmeta = attinmeta;
|
||||||
|
funcctx->max_calls = num_guc_file_variables;
|
||||||
|
MemoryContextSwitchTo(oldcontext);
|
||||||
|
}
|
||||||
|
|
||||||
|
funcctx = SRF_PERCALL_SETUP();
|
||||||
|
|
||||||
|
call_cntr = funcctx->call_cntr;
|
||||||
|
max_calls = funcctx->max_calls;
|
||||||
|
attinmeta = funcctx->attinmeta;
|
||||||
|
|
||||||
|
if (call_cntr < max_calls)
|
||||||
|
{
|
||||||
|
char *values[NUM_PG_FILE_SETTINGS_ATTS];
|
||||||
|
HeapTuple tuple;
|
||||||
|
Datum result;
|
||||||
|
ConfigFileVariable conf;
|
||||||
|
char buffer[12]; /* must be at least 12, per pg_ltoa */
|
||||||
|
|
||||||
|
/* Check to avoid going past end of array */
|
||||||
|
if (call_cntr > num_guc_file_variables)
|
||||||
|
SRF_RETURN_DONE(funcctx);
|
||||||
|
|
||||||
|
conf = guc_file_variables[call_cntr];
|
||||||
|
|
||||||
|
/* sourcefile */
|
||||||
|
values[0] = conf.filename;
|
||||||
|
|
||||||
|
/* sourceline */
|
||||||
|
pg_ltoa(conf.sourceline, buffer);
|
||||||
|
values[1] = pstrdup(buffer);
|
||||||
|
|
||||||
|
/* seqno */
|
||||||
|
pg_ltoa(call_cntr + 1, buffer);
|
||||||
|
values[2] = pstrdup(buffer);
|
||||||
|
|
||||||
|
/* name */
|
||||||
|
values[3] = conf.name;
|
||||||
|
|
||||||
|
/* setting */
|
||||||
|
values[4] = conf.value;
|
||||||
|
|
||||||
|
/* build a tuple */
|
||||||
|
tuple = BuildTupleFromCStrings(attinmeta, values);
|
||||||
|
|
||||||
|
/* make the tuple into a datum */
|
||||||
|
result = HeapTupleGetDatum(tuple);
|
||||||
|
|
||||||
|
SRF_RETURN_NEXT(funcctx, result);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SRF_RETURN_DONE(funcctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
_ShowOption(struct config_generic * record, bool use_units)
|
_ShowOption(struct config_generic * record, bool use_units)
|
||||||
{
|
{
|
||||||
|
@ -3060,6 +3060,8 @@ DATA(insert OID = 2078 ( set_config PGNSP PGUID 12 1 0 0 0 f f f f f f v 3 0 2
|
|||||||
DESCR("SET X as a function");
|
DESCR("SET X as a function");
|
||||||
DATA(insert OID = 2084 ( pg_show_all_settings PGNSP PGUID 12 1 1000 0 0 f f f f t t s 0 0 2249 "" "{25,25,25,25,25,25,25,25,25,25,25,1009,25,25,25,23}" "{o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}" "{name,setting,unit,category,short_desc,extra_desc,context,vartype,source,min_val,max_val,enumvals,boot_val,reset_val,sourcefile,sourceline}" _null_ _null_ show_all_settings _null_ _null_ _null_ ));
|
DATA(insert OID = 2084 ( pg_show_all_settings PGNSP PGUID 12 1 1000 0 0 f f f f t t s 0 0 2249 "" "{25,25,25,25,25,25,25,25,25,25,25,1009,25,25,25,23}" "{o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}" "{name,setting,unit,category,short_desc,extra_desc,context,vartype,source,min_val,max_val,enumvals,boot_val,reset_val,sourcefile,sourceline}" _null_ _null_ show_all_settings _null_ _null_ _null_ ));
|
||||||
DESCR("SHOW ALL as a function");
|
DESCR("SHOW ALL as a function");
|
||||||
|
DATA(insert OID = 3329 ( pg_show_all_file_settings PGNSP PGUID 12 1 1000 0 0 f f f f t t s 0 0 2249 "" "{25,23,23,25,25}" "{o,o,o,o,o}" "{sourcefile,sourceline,seqno,name,setting}" _null_ _null_ show_all_file_settings _null_ _null_ _null_ ));
|
||||||
|
DESCR("show config file settings");
|
||||||
DATA(insert OID = 1371 ( pg_lock_status PGNSP PGUID 12 1 1000 0 0 f f f f t t v 0 0 2249 "" "{25,26,26,23,21,25,28,26,26,21,25,23,25,16,16}" "{o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}" "{locktype,database,relation,page,tuple,virtualxid,transactionid,classid,objid,objsubid,virtualtransaction,pid,mode,granted,fastpath}" _null_ _null_ pg_lock_status _null_ _null_ _null_ ));
|
DATA(insert OID = 1371 ( pg_lock_status PGNSP PGUID 12 1 1000 0 0 f f f f t t v 0 0 2249 "" "{25,26,26,23,21,25,28,26,26,21,25,23,25,16,16}" "{o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}" "{locktype,database,relation,page,tuple,virtualxid,transactionid,classid,objid,objsubid,virtualtransaction,pid,mode,granted,fastpath}" _null_ _null_ pg_lock_status _null_ _null_ _null_ ));
|
||||||
DESCR("view system lock information");
|
DESCR("view system lock information");
|
||||||
DATA(insert OID = 1065 ( pg_prepared_xact PGNSP PGUID 12 1 1000 0 0 f f f f t t v 0 0 2249 "" "{28,25,1184,26,26}" "{o,o,o,o,o}" "{transaction,gid,prepared,ownerid,dbid}" _null_ _null_ pg_prepared_xact _null_ _null_ _null_ ));
|
DATA(insert OID = 1065 ( pg_prepared_xact PGNSP PGUID 12 1 1000 0 0 f f f f t t v 0 0 2249 "" "{28,25,1184,26,26}" "{o,o,o,o,o}" "{transaction,gid,prepared,ownerid,dbid}" _null_ _null_ pg_prepared_xact _null_ _null_ _null_ ));
|
||||||
|
@ -1100,6 +1100,7 @@ extern Datum quote_nullable(PG_FUNCTION_ARGS);
|
|||||||
extern Datum show_config_by_name(PG_FUNCTION_ARGS);
|
extern Datum show_config_by_name(PG_FUNCTION_ARGS);
|
||||||
extern Datum set_config_by_name(PG_FUNCTION_ARGS);
|
extern Datum set_config_by_name(PG_FUNCTION_ARGS);
|
||||||
extern Datum show_all_settings(PG_FUNCTION_ARGS);
|
extern Datum show_all_settings(PG_FUNCTION_ARGS);
|
||||||
|
extern Datum show_all_file_settings(PG_FUNCTION_ARGS);
|
||||||
|
|
||||||
/* lockfuncs.c */
|
/* lockfuncs.c */
|
||||||
extern Datum pg_lock_status(PG_FUNCTION_ARGS);
|
extern Datum pg_lock_status(PG_FUNCTION_ARGS);
|
||||||
|
@ -1312,6 +1312,12 @@ pg_cursors| SELECT c.name,
|
|||||||
c.is_scrollable,
|
c.is_scrollable,
|
||||||
c.creation_time
|
c.creation_time
|
||||||
FROM pg_cursor() c(name, statement, is_holdable, is_binary, is_scrollable, creation_time);
|
FROM pg_cursor() c(name, statement, is_holdable, is_binary, is_scrollable, creation_time);
|
||||||
|
pg_file_settings| SELECT a.sourcefile,
|
||||||
|
a.sourceline,
|
||||||
|
a.seqno,
|
||||||
|
a.name,
|
||||||
|
a.setting
|
||||||
|
FROM pg_show_all_file_settings() a(sourcefile, sourceline, seqno, name, setting);
|
||||||
pg_group| SELECT pg_authid.rolname AS groname,
|
pg_group| SELECT pg_authid.rolname AS groname,
|
||||||
pg_authid.oid AS grosysid,
|
pg_authid.oid AS grosysid,
|
||||||
ARRAY( SELECT pg_auth_members.member
|
ARRAY( SELECT pg_auth_members.member
|
||||||
|
Loading…
Reference in New Issue
Block a user