A client_encoding specification coming from the connection request has

to be processed by GUC before InitPostgres, because any required lookup
of the encoding conversion function has to be done during InitializeClientEncoding.
So, I broke this last week by moving GUC processing to after InitPostgres :-(.
What we can do as a compromise is process non-SUSET variables during
command line scanning (the same as before), and postpone the processing
of only SUSET variables.  None of the SUSET variables need to be set
before InitPostgres.
This commit is contained in:
Tom Lane 2004-11-24 19:51:05 +00:00
parent 5597fee8d7
commit cf796cc702
3 changed files with 78 additions and 43 deletions

View file

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.438 2004/11/20 00:48:58 tgl Exp $
* $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.439 2004/11/24 19:50:59 tgl Exp $
*
* NOTES
* this is the "main" module of the postgres backend and
@ -2205,7 +2205,7 @@ PostgresMain(int argc, char *argv[], const char *username)
bool secure;
int errs = 0;
int debug_flag = -1; /* -1 means not given */
List *guc_names = NIL; /* for possibly-SUSET options */
List *guc_names = NIL; /* for SUSET options */
List *guc_values = NIL;
GucContext ctx;
GucSource gucsource;
@ -2456,8 +2456,15 @@ PostgresMain(int argc, char *argv[], const char *username)
/*
* s - report usage statistics (timings) after each query
*
* Since log options are SUSET, we need to postpone unless
* still in secure context
*/
PendingConfigOption("log_statement_stats", "true");
if (ctx == PGC_BACKEND)
PendingConfigOption("log_statement_stats", "true");
else
SetConfigOption("log_statement_stats", "true",
ctx, gucsource);
break;
case 't':
@ -2490,7 +2497,12 @@ PostgresMain(int argc, char *argv[], const char *username)
break;
}
if (tmp)
PendingConfigOption(tmp, "true");
{
if (ctx == PGC_BACKEND)
PendingConfigOption(tmp, "true");
else
SetConfigOption(tmp, "true", ctx, gucsource);
}
break;
case 'v':
@ -2527,7 +2539,14 @@ PostgresMain(int argc, char *argv[], const char *username)
optarg)));
}
PendingConfigOption(name, value);
/*
* If a SUSET option, must postpone evaluation, unless
* we are still reading secure switches.
*/
if (ctx == PGC_BACKEND && IsSuperuserConfigOption(name))
PendingConfigOption(name, value);
else
SetConfigOption(name, value, ctx, gucsource);
free(name);
if (value)
free(value);
@ -2540,6 +2559,32 @@ PostgresMain(int argc, char *argv[], const char *username)
}
}
/*
* Process any additional GUC variable settings passed in startup
* packet. These are handled exactly like command-line variables.
*/
if (MyProcPort != NULL)
{
ListCell *gucopts = list_head(MyProcPort->guc_options);
while (gucopts)
{
char *name;
char *value;
name = lfirst(gucopts);
gucopts = lnext(gucopts);
value = lfirst(gucopts);
gucopts = lnext(gucopts);
if (IsSuperuserConfigOption(name))
PendingConfigOption(name, value);
else
SetConfigOption(name, value, PGC_BACKEND, PGC_S_CLIENT);
}
}
/* Acquire configuration parameters, unless inherited from postmaster */
if (!IsUnderPostmaster)
{
@ -2677,10 +2722,8 @@ PostgresMain(int argc, char *argv[], const char *username)
SetProcessingMode(NormalProcessing);
/*
* Now that we know if client is a superuser, we can apply GUC options
* that came from the client. (For option switches that are definitely
* not SUSET, we just went ahead and applied them above, but anything
* that is or might be SUSET has to be postponed to here.)
* Now that we know if client is a superuser, we can try to apply SUSET
* GUC options that came from the client.
*/
ctx = am_superuser ? PGC_SUSET : PGC_USERSET;
@ -2703,41 +2746,19 @@ PostgresMain(int argc, char *argv[], const char *username)
}
}
/*
* Process any additional GUC variable settings passed in startup
* packet.
*/
if (MyProcPort != NULL)
{
ListCell *gucopts = list_head(MyProcPort->guc_options);
while (gucopts)
{
char *name;
char *value;
name = lfirst(gucopts);
gucopts = lnext(gucopts);
value = lfirst(gucopts);
gucopts = lnext(gucopts);
SetConfigOption(name, value, ctx, PGC_S_CLIENT);
}
/*
* set up handler to log session end.
*/
if (IsUnderPostmaster && Log_disconnections)
on_proc_exit(log_disconnections, 0);
}
/*
* Now all GUC states are fully set up. Report them to client if
* appropriate.
*/
BeginReportingGUCOptions();
/*
* Also set up handler to log session end; we have to wait till now
* to be sure Log_disconnections has its final value.
*/
if (IsUnderPostmaster && Log_disconnections)
on_proc_exit(log_disconnections, 0);
/*
* Send this backend's cancellation info to the frontend.
*/

View file

@ -10,7 +10,7 @@
* Written by Peter Eisentraut <peter_e@gmx.net>.
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.249 2004/11/14 19:35:33 tgl Exp $
* $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.250 2004/11/24 19:51:03 tgl Exp $
*
*--------------------------------------------------------------------
*/
@ -3864,6 +3864,21 @@ GetConfigOptionResetString(const char *name)
return NULL;
}
/*
* Detect whether the given configuration option can only be set by
* a superuser.
*/
bool
IsSuperuserConfigOption(const char *name)
{
struct config_generic *record;
record = find_option(name, ERROR);
/* On an unrecognized name, don't error, just return false. */
if (record == NULL)
return false;
return (record->context == PGC_SUSET);
}
/*

View file

@ -7,7 +7,7 @@
* Copyright (c) 2000-2004, PostgreSQL Global Development Group
* Written by Peter Eisentraut <peter_e@gmx.net>.
*
* $PostgreSQL: pgsql/src/include/utils/guc.h,v 1.56 2004/11/14 19:35:35 tgl Exp $
* $PostgreSQL: pgsql/src/include/utils/guc.h,v 1.57 2004/11/24 19:51:05 tgl Exp $
*--------------------------------------------------------------------
*/
#ifndef GUC_H
@ -44,9 +44,7 @@
* given backend once it's started, but they can vary across backends.
*
* SUSET options can be set at postmaster startup, with the SIGHUP
* mechanism, or from SQL if you're a superuser. These options cannot
* be set in the connection startup packet, because when it is processed
* we don't yet know if the user is a superuser.
* mechanism, or from SQL if you're a superuser.
*
* USERSET options can be set by anyone any time.
*/
@ -177,6 +175,7 @@ extern void EmitWarningsOnPlaceholders(const char *className);
extern const char *GetConfigOption(const char *name);
extern const char *GetConfigOptionResetString(const char *name);
extern bool IsSuperuserConfigOption(const char *name);
extern void ProcessConfigFile(GucContext context);
extern void InitializeGUCOptions(void);
extern bool SelectConfigFiles(const char *userDoption, const char *progname);