A client_encoding specification coming from the connection request has
authorTom Lane
Wed, 24 Nov 2004 19:51:05 +0000 (19:51 +0000)
committerTom Lane
Wed, 24 Nov 2004 19:51:05 +0000 (19:51 +0000)
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.

src/backend/tcop/postgres.c
src/backend/utils/misc/guc.c
src/include/utils/guc.h

index 9b3c14399c978e83fbf88f4136b3a1a819115a62..893a7b95cdcd457e589c153a2f5f37cdaac50f41 100644 (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.
     */
index 581a96caa2623f04740bc6434947caaaf20ddd40..fd13c41a35bd5230229555094fac6f98f3c4b4bb 100644 (file)
@@ -10,7 +10,7 @@
  * Written by Peter Eisentraut .
  *
  * 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);
+}
 
 
 /*
index f5f4a78fe4d3a3bfc943bb96e46524e89efae966..786d696620363d3553341b6e4350861db4e16b01 100644 (file)
@@ -7,7 +7,7 @@
  * Copyright (c) 2000-2004, PostgreSQL Global Development Group
  * Written by Peter Eisentraut .
  *
- * $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);