mirror of
https://github.com/postgres/postgres.git
synced 2025-09-03 15:22:11 +03:00
In the continuing saga of FE/BE protocol revisions, add reporting of
initial values and runtime changes in selected parameters. This gets rid of the need for an initial 'select pg_client_encoding()' query in libpq, bringing us back to one message transmitted in each direction for a standard connection startup. To allow server version to be sent using the same GUC mechanism that handles other parameters, invent the concept of a never-settable GUC parameter: you can 'show server_version' but it's not settable by any GUC input source. Create 'lc_collate' and 'lc_ctype' never-settable parameters so that people can find out these settings without need for pg_controldata. (These side ideas were all discussed some time ago in pgsql-hackers, but not yet implemented.)
This commit is contained in:
@@ -5,10 +5,13 @@
|
||||
* command, configuration file, and command line options.
|
||||
* See src/backend/utils/misc/README for more information.
|
||||
*
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.118 2003/03/28 20:17:13 tgl Exp $
|
||||
*
|
||||
* Copyright 2000 by PostgreSQL Global Development Group
|
||||
* Copyright 2000-2003 by PostgreSQL Global Development Group
|
||||
* Written by Peter Eisentraut <peter_e@gmx.net>.
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.119 2003/04/25 19:45:09 tgl Exp $
|
||||
*
|
||||
*--------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
@@ -32,6 +35,7 @@
|
||||
#include "funcapi.h"
|
||||
#include "libpq/auth.h"
|
||||
#include "libpq/pqcomm.h"
|
||||
#include "libpq/pqformat.h"
|
||||
#include "mb/pg_wchar.h"
|
||||
#include "miscadmin.h"
|
||||
#include "optimizer/cost.h"
|
||||
@@ -52,7 +56,12 @@
|
||||
#include "pgstat.h"
|
||||
|
||||
|
||||
/* XXX these should be in other modules' header files */
|
||||
#ifndef PG_KRB_SRVTAB
|
||||
#define PG_KRB_SRVTAB ""
|
||||
#endif
|
||||
|
||||
|
||||
/* XXX these should appear in other modules' header files */
|
||||
extern bool Log_connections;
|
||||
extern int PreAuthDelay;
|
||||
extern int AuthenticationTimeout;
|
||||
@@ -70,9 +79,18 @@ static const char *assign_facility(const char *facility,
|
||||
bool doit, bool interactive);
|
||||
#endif
|
||||
|
||||
static const char *assign_defaultxactisolevel(const char *newval,
|
||||
bool doit, bool interactive);
|
||||
static const char *assign_log_min_messages(const char *newval,
|
||||
bool doit, bool interactive);
|
||||
static const char *assign_client_min_messages(const char *newval,
|
||||
bool doit, bool interactive);
|
||||
static const char *assign_min_error_statement(const char *newval, bool doit,
|
||||
bool interactive);
|
||||
static const char *assign_msglvl(int *var, const char *newval,
|
||||
bool doit, bool interactive);
|
||||
|
||||
|
||||
/*
|
||||
* Debugging options
|
||||
*/
|
||||
@@ -85,6 +103,7 @@ bool Debug_print_plan = false;
|
||||
bool Debug_print_parse = false;
|
||||
bool Debug_print_rewritten = false;
|
||||
bool Debug_pretty_print = false;
|
||||
bool Explain_pretty_print = true;
|
||||
|
||||
bool log_parser_stats = false;
|
||||
bool log_planner_stats = false;
|
||||
@@ -93,8 +112,6 @@ bool log_statement_stats = false; /* this is sort of all
|
||||
* three above together */
|
||||
bool log_btree_build_stats = false;
|
||||
|
||||
bool Explain_pretty_print = true;
|
||||
|
||||
bool SQL_inheritance = true;
|
||||
|
||||
bool Australian_timezones = false;
|
||||
@@ -102,40 +119,31 @@ bool Australian_timezones = false;
|
||||
bool Password_encryption = true;
|
||||
|
||||
int log_min_error_statement = PANIC;
|
||||
char *log_min_error_statement_str = NULL;
|
||||
const char log_min_error_statement_str_default[] = "panic";
|
||||
|
||||
int log_min_messages = NOTICE;
|
||||
char *log_min_messages_str = NULL;
|
||||
const char log_min_messages_str_default[] = "notice";
|
||||
|
||||
int client_min_messages = NOTICE;
|
||||
char *client_min_messages_str = NULL;
|
||||
const char client_min_messages_str_default[] = "notice";
|
||||
|
||||
|
||||
#ifndef PG_KRB_SRVTAB
|
||||
#define PG_KRB_SRVTAB ""
|
||||
#endif
|
||||
|
||||
/*
|
||||
* These variables are all dummies that don't do anything, except in some
|
||||
* cases provide the value for SHOW to display. The real state is elsewhere
|
||||
* and is kept in sync by assign_hooks.
|
||||
*/
|
||||
static char *log_min_error_statement_str;
|
||||
static char *log_min_messages_str;
|
||||
static char *client_min_messages_str;
|
||||
static double phony_random_seed;
|
||||
static char *client_encoding_string;
|
||||
static char *datestyle_string;
|
||||
static char *default_iso_level_string;
|
||||
static char *locale_collate;
|
||||
static char *locale_ctype;
|
||||
static char *regex_flavor_string;
|
||||
static char *server_encoding_string;
|
||||
static char *server_version_string;
|
||||
static char *session_authorization_string;
|
||||
static char *timezone_string;
|
||||
static char *XactIsoLevel_string;
|
||||
|
||||
static const char *assign_defaultxactisolevel(const char *newval,
|
||||
bool doit, bool interactive);
|
||||
|
||||
|
||||
/*
|
||||
* Declarations for GUC tables
|
||||
@@ -171,6 +179,7 @@ struct config_generic
|
||||
#define GUC_LIST_QUOTE 0x0002 /* double-quote list elements */
|
||||
#define GUC_NO_SHOW_ALL 0x0004 /* exclude from SHOW ALL */
|
||||
#define GUC_NO_RESET_ALL 0x0008 /* exclude from RESET ALL */
|
||||
#define GUC_REPORT 0x0010 /* auto-report changes to client */
|
||||
|
||||
/* bit values in status field */
|
||||
#define GUC_HAVE_TENTATIVE 0x0001 /* tentative value is defined */
|
||||
@@ -763,22 +772,24 @@ static struct config_string
|
||||
ConfigureNamesString[] =
|
||||
{
|
||||
{
|
||||
{"client_encoding", PGC_USERSET}, &client_encoding_string,
|
||||
{"client_encoding", PGC_USERSET, GUC_REPORT},
|
||||
&client_encoding_string,
|
||||
"SQL_ASCII", assign_client_encoding, NULL
|
||||
},
|
||||
|
||||
{
|
||||
{"client_min_messages", PGC_USERSET}, &client_min_messages_str,
|
||||
client_min_messages_str_default, assign_client_min_messages, NULL
|
||||
"notice", assign_client_min_messages, NULL
|
||||
},
|
||||
|
||||
{
|
||||
{"log_min_error_statement", PGC_USERSET}, &log_min_error_statement_str,
|
||||
log_min_error_statement_str_default, assign_min_error_statement, NULL
|
||||
"panic", assign_min_error_statement, NULL
|
||||
},
|
||||
|
||||
{
|
||||
{"DateStyle", PGC_USERSET, GUC_LIST_INPUT}, &datestyle_string,
|
||||
{"DateStyle", PGC_USERSET, GUC_LIST_INPUT | GUC_REPORT},
|
||||
&datestyle_string,
|
||||
"ISO, US", assign_datestyle, show_datestyle
|
||||
},
|
||||
|
||||
@@ -799,6 +810,16 @@ static struct config_string
|
||||
|
||||
/* See main.c about why defaults for LC_foo are not all alike */
|
||||
|
||||
{
|
||||
{"lc_collate", PGC_INTERNAL}, &locale_collate,
|
||||
"C", NULL, NULL
|
||||
},
|
||||
|
||||
{
|
||||
{"lc_ctype", PGC_INTERNAL}, &locale_ctype,
|
||||
"C", NULL, NULL
|
||||
},
|
||||
|
||||
{
|
||||
{"lc_messages", PGC_SUSET}, &locale_messages,
|
||||
"", locale_messages_assign, NULL
|
||||
@@ -837,13 +858,20 @@ static struct config_string
|
||||
},
|
||||
|
||||
{
|
||||
{"server_encoding", PGC_USERSET}, &server_encoding_string,
|
||||
"SQL_ASCII", assign_server_encoding, show_server_encoding
|
||||
{"server_encoding", PGC_INTERNAL, GUC_REPORT},
|
||||
&server_encoding_string,
|
||||
"SQL_ASCII", NULL, NULL
|
||||
},
|
||||
|
||||
{
|
||||
{"server_version", PGC_INTERNAL, GUC_REPORT},
|
||||
&server_version_string,
|
||||
PG_VERSION, NULL, NULL
|
||||
},
|
||||
|
||||
{
|
||||
{"log_min_messages", PGC_USERSET}, &log_min_messages_str,
|
||||
log_min_messages_str_default, assign_log_min_messages, NULL
|
||||
"notice", assign_log_min_messages, NULL
|
||||
},
|
||||
|
||||
{
|
||||
@@ -910,10 +938,13 @@ static int num_guc_variables;
|
||||
|
||||
static bool guc_dirty; /* TRUE if need to do commit/abort work */
|
||||
|
||||
static bool reporting_enabled; /* TRUE to enable GUC_REPORT */
|
||||
|
||||
static char *guc_string_workspace; /* for avoiding memory leaks */
|
||||
|
||||
|
||||
static int guc_var_compare(const void *a, const void *b);
|
||||
static void ReportGUCOption(struct config_generic *record);
|
||||
static char *_ShowOption(struct config_generic * record);
|
||||
|
||||
|
||||
@@ -1182,6 +1213,8 @@ InitializeGUCOptions(void)
|
||||
|
||||
guc_dirty = false;
|
||||
|
||||
reporting_enabled = false;
|
||||
|
||||
guc_string_workspace = NULL;
|
||||
|
||||
/*
|
||||
@@ -1325,6 +1358,9 @@ ResetAllOptions(void)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (gconf->flags & GUC_REPORT)
|
||||
ReportGUCOption(gconf);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1351,11 +1387,14 @@ AtEOXact_GUC(bool isCommit)
|
||||
for (i = 0; i < num_guc_variables; i++)
|
||||
{
|
||||
struct config_generic *gconf = guc_variables[i];
|
||||
bool changed;
|
||||
|
||||
/* Skip if nothing's happened to this var in this transaction */
|
||||
if (gconf->status == 0)
|
||||
continue;
|
||||
|
||||
changed = false;
|
||||
|
||||
switch (gconf->vartype)
|
||||
{
|
||||
case PGC_BOOL:
|
||||
@@ -1375,6 +1414,7 @@ AtEOXact_GUC(bool isCommit)
|
||||
true, false))
|
||||
elog(LOG, "Failed to commit %s", conf->gen.name);
|
||||
*conf->variable = conf->session_val;
|
||||
changed = true;
|
||||
}
|
||||
conf->gen.source = conf->gen.session_source;
|
||||
conf->gen.status = 0;
|
||||
@@ -1397,6 +1437,7 @@ AtEOXact_GUC(bool isCommit)
|
||||
true, false))
|
||||
elog(LOG, "Failed to commit %s", conf->gen.name);
|
||||
*conf->variable = conf->session_val;
|
||||
changed = true;
|
||||
}
|
||||
conf->gen.source = conf->gen.session_source;
|
||||
conf->gen.status = 0;
|
||||
@@ -1419,6 +1460,7 @@ AtEOXact_GUC(bool isCommit)
|
||||
true, false))
|
||||
elog(LOG, "Failed to commit %s", conf->gen.name);
|
||||
*conf->variable = conf->session_val;
|
||||
changed = true;
|
||||
}
|
||||
conf->gen.source = conf->gen.session_source;
|
||||
conf->gen.status = 0;
|
||||
@@ -1460,18 +1502,72 @@ AtEOXact_GUC(bool isCommit)
|
||||
}
|
||||
|
||||
SET_STRING_VARIABLE(conf, str);
|
||||
changed = true;
|
||||
}
|
||||
conf->gen.source = conf->gen.session_source;
|
||||
conf->gen.status = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (changed && (gconf->flags & GUC_REPORT))
|
||||
ReportGUCOption(gconf);
|
||||
}
|
||||
|
||||
guc_dirty = false;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Start up automatic reporting of changes to variables marked GUC_REPORT.
|
||||
* This is executed at completion of backend startup.
|
||||
*/
|
||||
void
|
||||
BeginReportingGUCOptions(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Don't do anything unless talking to an interactive frontend of
|
||||
* protocol 3.0 or later.
|
||||
*/
|
||||
if (whereToSendOutput != Remote ||
|
||||
PG_PROTOCOL_MAJOR(FrontendProtocol) < 3)
|
||||
return;
|
||||
|
||||
reporting_enabled = true;
|
||||
|
||||
/* Transmit initial values of interesting variables */
|
||||
for (i = 0; i < num_guc_variables; i++)
|
||||
{
|
||||
struct config_generic *conf = guc_variables[i];
|
||||
|
||||
if (conf->flags & GUC_REPORT)
|
||||
ReportGUCOption(conf);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* ReportGUCOption: if appropriate, transmit option value to frontend
|
||||
*/
|
||||
static void
|
||||
ReportGUCOption(struct config_generic *record)
|
||||
{
|
||||
if (reporting_enabled && (record->flags & GUC_REPORT))
|
||||
{
|
||||
char *val = _ShowOption(record);
|
||||
StringInfoData msgbuf;
|
||||
|
||||
pq_beginmessage(&msgbuf, 'S');
|
||||
pq_sendstring(&msgbuf, record->name);
|
||||
pq_sendstring(&msgbuf, val);
|
||||
pq_endmessage(&msgbuf);
|
||||
|
||||
pfree(val);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Try to interpret value as boolean value. Valid values are: true,
|
||||
* false, yes, no, on, off, 1, 0. If the string parses okay, return
|
||||
@@ -1638,6 +1734,16 @@ set_config_option(const char *name, const char *value,
|
||||
*/
|
||||
switch (record->context)
|
||||
{
|
||||
case PGC_INTERNAL:
|
||||
if (context == PGC_SIGHUP)
|
||||
return true;
|
||||
if (context != PGC_INTERNAL)
|
||||
{
|
||||
elog(elevel, "'%s' cannot be changed",
|
||||
name);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case PGC_POSTMASTER:
|
||||
if (context == PGC_SIGHUP)
|
||||
return true;
|
||||
@@ -2054,6 +2160,9 @@ set_config_option(const char *name, const char *value,
|
||||
}
|
||||
}
|
||||
|
||||
if (DoIt && (record->flags & GUC_REPORT))
|
||||
ReportGUCOption(record);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2614,8 +2723,10 @@ show_all_settings(PG_FUNCTION_ARGS)
|
||||
SRF_RETURN_NEXT(funcctx, result);
|
||||
}
|
||||
else
|
||||
/* do when there is no more left */
|
||||
{
|
||||
/* do when there is no more left */
|
||||
SRF_RETURN_DONE(funcctx);
|
||||
}
|
||||
}
|
||||
|
||||
static char *
|
||||
@@ -2736,52 +2847,6 @@ ParseLongOption(const char *string, char **name, char **value)
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef HAVE_SYSLOG
|
||||
|
||||
static const char *
|
||||
assign_facility(const char *facility, bool doit, bool interactive)
|
||||
{
|
||||
if (strcasecmp(facility, "LOCAL0") == 0)
|
||||
return facility;
|
||||
if (strcasecmp(facility, "LOCAL1") == 0)
|
||||
return facility;
|
||||
if (strcasecmp(facility, "LOCAL2") == 0)
|
||||
return facility;
|
||||
if (strcasecmp(facility, "LOCAL3") == 0)
|
||||
return facility;
|
||||
if (strcasecmp(facility, "LOCAL4") == 0)
|
||||
return facility;
|
||||
if (strcasecmp(facility, "LOCAL5") == 0)
|
||||
return facility;
|
||||
if (strcasecmp(facility, "LOCAL6") == 0)
|
||||
return facility;
|
||||
if (strcasecmp(facility, "LOCAL7") == 0)
|
||||
return facility;
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static const char *
|
||||
assign_defaultxactisolevel(const char *newval, bool doit, bool interactive)
|
||||
{
|
||||
if (strcasecmp(newval, "serializable") == 0)
|
||||
{
|
||||
if (doit)
|
||||
DefaultXactIsoLevel = XACT_SERIALIZABLE;
|
||||
}
|
||||
else if (strcasecmp(newval, "read committed") == 0)
|
||||
{
|
||||
if (doit)
|
||||
DefaultXactIsoLevel = XACT_READ_COMMITTED;
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
return newval;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Handle options fetched from pg_database.datconfig or pg_shadow.useconfig.
|
||||
* The array parameter must be an array of TEXT (it must not be NULL).
|
||||
@@ -2993,21 +3058,70 @@ GUCArrayDelete(ArrayType *array, const char *name)
|
||||
return newarray;
|
||||
}
|
||||
|
||||
const char *
|
||||
|
||||
/*
|
||||
* assign_hook subroutines
|
||||
*/
|
||||
|
||||
#ifdef HAVE_SYSLOG
|
||||
|
||||
static const char *
|
||||
assign_facility(const char *facility, bool doit, bool interactive)
|
||||
{
|
||||
if (strcasecmp(facility, "LOCAL0") == 0)
|
||||
return facility;
|
||||
if (strcasecmp(facility, "LOCAL1") == 0)
|
||||
return facility;
|
||||
if (strcasecmp(facility, "LOCAL2") == 0)
|
||||
return facility;
|
||||
if (strcasecmp(facility, "LOCAL3") == 0)
|
||||
return facility;
|
||||
if (strcasecmp(facility, "LOCAL4") == 0)
|
||||
return facility;
|
||||
if (strcasecmp(facility, "LOCAL5") == 0)
|
||||
return facility;
|
||||
if (strcasecmp(facility, "LOCAL6") == 0)
|
||||
return facility;
|
||||
if (strcasecmp(facility, "LOCAL7") == 0)
|
||||
return facility;
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static const char *
|
||||
assign_defaultxactisolevel(const char *newval, bool doit, bool interactive)
|
||||
{
|
||||
if (strcasecmp(newval, "serializable") == 0)
|
||||
{
|
||||
if (doit)
|
||||
DefaultXactIsoLevel = XACT_SERIALIZABLE;
|
||||
}
|
||||
else if (strcasecmp(newval, "read committed") == 0)
|
||||
{
|
||||
if (doit)
|
||||
DefaultXactIsoLevel = XACT_READ_COMMITTED;
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
return newval;
|
||||
}
|
||||
|
||||
static const char *
|
||||
assign_log_min_messages(const char *newval,
|
||||
bool doit, bool interactive)
|
||||
{
|
||||
return (assign_msglvl(&log_min_messages, newval, doit, interactive));
|
||||
}
|
||||
|
||||
const char *
|
||||
static const char *
|
||||
assign_client_min_messages(const char *newval,
|
||||
bool doit, bool interactive)
|
||||
{
|
||||
return (assign_msglvl(&client_min_messages, newval, doit, interactive));
|
||||
}
|
||||
|
||||
const char *
|
||||
static const char *
|
||||
assign_min_error_statement(const char *newval, bool doit, bool interactive)
|
||||
{
|
||||
return (assign_msglvl(&log_min_error_statement, newval, doit, interactive));
|
||||
@@ -3087,4 +3201,5 @@ assign_msglvl(int *var, const char *newval, bool doit, bool interactive)
|
||||
return newval; /* OK */
|
||||
}
|
||||
|
||||
|
||||
#include "guc-file.c"
|
||||
|
Reference in New Issue
Block a user