In the continuing saga of FE/BE protocol revisions, add reporting of
authorTom Lane
Fri, 25 Apr 2003 19:45:10 +0000 (19:45 +0000)
committerTom Lane
Fri, 25 Apr 2003 19:45:10 +0000 (19:45 +0000)
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.)

13 files changed:
doc/src/sgml/protocol.sgml
doc/src/sgml/ref/set.sgml
doc/src/sgml/ref/show.sgml
src/backend/access/transam/xlog.c
src/backend/commands/variable.c
src/backend/utils/init/postinit.c
src/backend/utils/misc/guc.c
src/include/commands/variable.h
src/include/libpq/pqcomm.h
src/include/utils/guc.h
src/interfaces/libpq/fe-connect.c
src/interfaces/libpq/fe-exec.c
src/interfaces/libpq/libpq-int.h

index 7b5f9593a985fbb4517c91488dff3e546423f418..70c255f00ce5930bcc3917e3a27b78d7840c4afc 100644 (file)
@@ -1,4 +1,4 @@
-
+
 
 
  Frontend/Backend Protocol
     is being started, and the frontend is just an interested bystander.
     It is still possible for the startup attempt
     to fail (ErrorResponse), but in the normal case the backend will send
-    BackendKeyData, some ParameterStatus messages, and finally ReadyForQuery.
+    some ParameterStatus messages, BackendKeyData, and finally ReadyForQuery.
    
 
    
    
     At present there is a hard-wired set of parameters for which
     ParameterStatus will be generated: they are
-    version (backend version,
-    a pseudo-parameter that cannot change after startup); 
-    database_encoding (also not presently changeable after start);
+    server_version (a pseudo-parameter that cannot change after
+    startup);
+    server_encoding (also not presently changeable after start);
     client_encoding, and
     DateStyle.
     This set might change in the future, or even become configurable.
@@ -3881,6 +3881,13 @@ The CopyInResponse and CopyOutResponse messages carry a field indicating
 whether the COPY operation is text or binary.
 
 
+
+The backend sends ParameterStatus ('S') messages during connection
+startup for all parameters it considers interesting to the client library.
+Subsequently, a ParameterStatus message is sent whenever the active value
+changes for any of these parameters.
+
+
 
 The CursorResponse ('P') message is no longer generated by
 the backend.
index 23b77dff5c5a723d813967afa0607d436c1769af..75dc366c3f945085637d44a56576571ab984c9ec 100644 (file)
@@ -1,5 +1,5 @@
 
 
@@ -52,7 +52,7 @@ SET [ SESSION | LOCAL ] TIME ZONE { timezone
       variable
       
        
-        A settable run-time parameter.
+        Name of a settable run-time parameter.
        
       
      
@@ -79,8 +79,9 @@ SET [ SESSION | LOCAL ] TIME ZONE { timezone
 
   
    The SET command changes run-time configuration
-   parameters.  Many of the run-time parameters listed in the
-    can be changed on-the-fly with SET.
+   parameters.  Many of the run-time parameters listed in
+    can be changed on-the-fly with
+   SET.
    (But some require superuser privileges to change, and others cannot
    be changed after server or session start.)  Note that
    SET only affects the value used by the current
@@ -123,7 +124,7 @@ SET [ SESSION | LOCAL ] TIME ZONE { timezone
      
       
        Choose the date/time representation style. Two separate
-       settings are involved: the default date/time output and the
+       settings are involved: the default date/time output format and the
        interpretation of ambiguous input.
       
 
@@ -147,7 +148,7 @@ SET [ SESSION | LOCAL ] TIME ZONE { timezone
           
            Use Oracle/Ingres-style dates and times. Note that this
            style has nothing to do with SQL (which mandates ISO 8601
-           style), the naming of this option is a historical accident.
+           style); the naming of this option is a historical accident.
           
          
         
@@ -283,17 +284,6 @@ SELECT setseed(value);
      
     
 
-    
-     SERVER_ENCODING
-     
-      
-       Shows the server-side multibyte encoding.  (At present, this
-       parameter can be shown but not set, because the encoding is
-       determined at initdb time.)
-      
-     
-    
-
     
      TIME ZONE
      TIMEZONE
@@ -410,7 +400,7 @@ SELECT setseed(value);
     
      
     
-     ERROR:  'name is not a
+     ERROR:  'name' is not a
     valid option name
      
       
@@ -447,7 +437,7 @@ SELECT setseed(value);
   Notes
 
   
-   The function set_config provides the equivalent
+   The function set_config provides equivalent
    capability. See .
   
  
@@ -517,6 +507,8 @@ SELECT CURRENT_TIMESTAMP AS today;
   See Also
 
   
+   ,
+   ,
    ,
    ,
    
index 832c4392cbf27d003baa4614b1d0cd1e7d4d5f68..0fec5fcce557cefc003d236d62a450ca0dabe198 100644 (file)
@@ -1,5 +1,5 @@
 
 
@@ -52,12 +52,13 @@ SHOW ALL
  
   Description
   
-   SHOW will display the current setting of a
-   run-time parameter. These variables can be set using the
+   SHOW will display the current setting of
+   run-time parameters. These variables can be set using the
    SET statement, by editing the
-   postgresql.conf, through the
-   PGOPTIONS environmental variable, or through a
-   command-line flag when starting the
+   postgresql.conf configuration file, through the
+   PGOPTIONS environmental variable (when using libpq
+   or a libpq-based application), or through
+   command-line flags when starting the
    postmaster.
   
 
@@ -66,6 +67,64 @@ SHOW ALL
    does not start a new transaction block. See the
    autocommit section in  for details.
   
+
+  
+   Available parameters are documented in
+    and on the
+    reference page.
+   In addition, there are a few parameters that can be shown but not set:
+
+   
+
+    
+     SERVER_VERSION
+     
+      
+       Shows the server's version number.
+      
+     
+    
+
+    
+     SERVER_ENCODING
+     
+      
+       Shows the server-side multibyte encoding.  At present, this
+       parameter can be shown but not set, because the encoding is
+       determined at database creation time.
+      
+     
+    
+
+    
+     LC_COLLATE
+     
+      
+       Shows the database's locale setting for collation (text ordering).
+       At present, this parameter can be shown but not set, because the
+       setting is determined at initdb time.
+      
+     
+    
+
+    
+     LC_CTYPE
+     
+      
+       Shows the database's locale setting for character set considerations.
+       At present, this parameter can be shown but not set, because the
+       setting is determined at initdb time.
+      
+     
+    
+
+   
+  
+
+  
+   Use  to set the value
+   of settable parameters.
+  
  
 
  
@@ -79,7 +138,7 @@ SHOW ALL
       
        
    Message returned if name does
-   not stand for an existing parameter.
+   not stand for a known parameter.
        
       
      
index 4030a11a52e5f265cccfd699de44fcac336dfba3..d1523dc89b038177f0e718d5cd7a1b6adea5658a 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Header: /cvsroot/pgsql/src/backend/access/transam/xlog.c,v 1.113 2003/04/18 01:03:41 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/transam/xlog.c,v 1.114 2003/04/25 19:45:08 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -36,6 +36,7 @@
 #include "storage/sinval.h"
 #include "storage/spin.h"
 #include "utils/builtins.h"
+#include "utils/guc.h"
 #include "utils/relcache.h"
 #include "miscadmin.h"
 
@@ -2260,6 +2261,12 @@ ReadControlFile(void)
             "\twhich is not recognized by setlocale().\n"
             "\tIt looks like you need to initdb.",
             ControlFile->lc_ctype);
+
+   /* Make the fixed locale settings visible as GUC variables, too */
+   SetConfigOption("lc_collate", ControlFile->lc_collate,
+                   PGC_INTERNAL, PGC_S_OVERRIDE);
+   SetConfigOption("lc_ctype", ControlFile->lc_ctype,
+                   PGC_INTERNAL, PGC_S_OVERRIDE);
 }
 
 void
index 6ce1487e86ef4c32feb2319dfd4c40da79a9f99b..7b23cc80d0094180bad0b00d8fb7ba675cc55d3b 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/commands/variable.c,v 1.73 2003/02/01 18:31:28 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/commands/variable.c,v 1.74 2003/04/25 19:45:08 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -500,22 +500,6 @@ assign_client_encoding(const char *value, bool doit, bool interactive)
 }
 
 
-const char *
-assign_server_encoding(const char *value, bool doit, bool interactive)
-{
-   if (interactive)
-       elog(ERROR, "SET SERVER_ENCODING is not supported");
-   /* Pretend never to fail in noninteractive case */
-   return value;
-}
-
-const char *
-show_server_encoding(void)
-{
-   return GetDatabaseEncodingName();
-}
-
-
 /*
  * SET SESSION AUTHORIZATION
  *
index 36dd3c7b5c2c3fa1f6e7acbe54740c48b7b09773..4d76e69ac995961f3fa413f77fe01b2334cd96a1 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/utils/init/postinit.c,v 1.119 2003/02/19 14:31:26 ishii Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/utils/init/postinit.c,v 1.120 2003/04/25 19:45:08 tgl Exp $
  *
  *
  *-------------------------------------------------------------------------
@@ -128,6 +128,9 @@ ReverifyMyDatabase(const char *name)
     * info out of the pg_database tuple.
     */
    SetDatabaseEncoding(dbform->encoding);
+   /* Record it as a GUC internal option, too */
+   SetConfigOption("server_encoding", GetDatabaseEncodingName(),
+                   PGC_INTERNAL, PGC_S_OVERRIDE);
    /* If we have no other source of client_encoding, use server encoding */
    SetConfigOption("client_encoding", GetDatabaseEncodingName(),
                    PGC_BACKEND, PGC_S_DEFAULT);
@@ -400,6 +403,12 @@ InitPostgres(const char *dbname, const char *username)
    /* initialize client encoding */
    InitializeClientEncoding();
 
+   /*
+    * Now all default states are fully set up.  Report them to client
+    * if appropriate.
+    */
+   BeginReportingGUCOptions();
+
    /*
     * Set up process-exit callback to do pre-shutdown cleanup.  This
     * should be last because we want shmem_exit to call this routine
index 89b625277971b3c660d327864d20ccb92f807aa1..f18c74c472afe5429bebade24efe3034d78c05c8 100644 (file)
@@ -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 .
+ *
+ * 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"
 #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"
index 73687178fe8439cd27295f3bdfa670df60cd6b3e..68a0ebf7450e15a568fbf659e076ca42547e6d4a 100644 (file)
@@ -2,7 +2,7 @@
  * variable.h
  *     Routines for handling specialized SET variables.
  *
- * $Id: variable.h,v 1.19 2002/09/04 20:31:42 momjian Exp $
+ * $Id: variable.h,v 1.20 2003/04/25 19:45:09 tgl Exp $
  *
  */
 #ifndef VARIABLE_H
@@ -22,9 +22,6 @@ extern bool assign_random_seed(double value,
 extern const char *show_random_seed(void);
 extern const char *assign_client_encoding(const char *value,
                       bool doit, bool interactive);
-extern const char *assign_server_encoding(const char *value,
-                      bool doit, bool interactive);
-extern const char *show_server_encoding(void);
 extern const char *assign_session_authorization(const char *value,
                             bool doit, bool interactive);
 extern const char *show_session_authorization(void);
index 4f458c51c29a5312fa5c3eb47186a550d733de8b..6a871c7c6f61ec427a0f327edc66b5f66586d8c1 100644 (file)
@@ -9,7 +9,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pqcomm.h,v 1.79 2003/04/24 21:16:44 tgl Exp $
+ * $Id: pqcomm.h,v 1.80 2003/04/25 19:45:09 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -106,7 +106,7 @@ typedef union SockAddr
 /* The earliest and latest frontend/backend protocol version supported. */
 
 #define PG_PROTOCOL_EARLIEST   PG_PROTOCOL(1,0)
-#define PG_PROTOCOL_LATEST     PG_PROTOCOL(3,103) /* XXX temporary value */
+#define PG_PROTOCOL_LATEST     PG_PROTOCOL(3,104) /* XXX temporary value */
 
 typedef uint32 ProtocolVersion; /* FE/BE protocol version number */
 
index f39f0a18544ad6ba35c022448a6de84d0778168d..47a5eeab18723b2eba11c00a53a91d2052671fd0 100644 (file)
@@ -1,10 +1,14 @@
-/*
+/*--------------------------------------------------------------------
  * guc.h
  *
  * External declarations pertaining to backend/utils/misc/guc.c and
  * backend/utils/misc/guc-file.l
  *
- * $Id: guc.h,v 1.26 2002/11/15 00:47:22 momjian Exp $
+ * Copyright 2000-2003 by PostgreSQL Global Development Group
+ * Written by Peter Eisentraut .
+ *
+ * $Id: guc.h,v 1.27 2003/04/25 19:45:09 tgl Exp $
+ *--------------------------------------------------------------------
  */
 #ifndef GUC_H
 #define GUC_H
  * Certain options can only be set at certain times. The rules are
  * like this:
  *
+ * INTERNAL options cannot be set by the user at all, but only through
+ * internal processes ("server_version" is an example).  These are GUC
+ * variables only so they can be shown by SHOW, etc.
+ *
  * POSTMASTER options can only be set when the postmaster starts,
  * either from the configuration file or the command line.
  *
  * SIGHUP options can only be set at postmaster startup or by changing
  * the configuration file and sending the HUP signal to the postmaster
  * or a backend process. (Notice that the signal receipt will not be
- * evaluated immediately. The postmaster and the backend block at a
+ * evaluated immediately. The postmaster and the backend check it at a
  * certain point in their main loop. It's safer to wait than to read a
  * file asynchronously.)
  *
  * BACKEND options can only be set at postmaster startup, from the
- * configuration file, or with the PGOPTIONS variable from the client
- * when the connection is initiated.  Furthermore, an already-started
- * backend will ignore changes to such an option in the configuration
- * file.  The idea is that these options are fixed for a given backend
- * once it's started, but they can vary across backends.
+ * configuration file, or by client request in the connection startup
+ * packet (e.g., from libpq's PGOPTIONS variable).  Furthermore, an
+ * already-started backend will ignore changes to such an option in the
+ * configuration file.  The idea is that these options are fixed for a
+ * 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 using the PGOPTIONS mechanism, because there is not check as
- * to who does this.
+ * be set in the connection startup packet, because when it is processed
+ * we don't yet know if the user is a superuser.
  *
  * USERSET options can be set by anyone any time.
  */
 typedef enum
 {
+   PGC_INTERNAL,
    PGC_POSTMASTER,
    PGC_SIGHUP,
    PGC_BACKEND,
@@ -57,7 +66,8 @@ typedef enum
  * override the postmaster command line.)  Tracking the source allows us
  * to process sources in any convenient order without affecting results.
  * Sources <= PGC_S_OVERRIDE will set the default used by RESET, as well
- * as the current value.
+ * as the current value.  Note that source == PGC_S_OVERRIDE should be
+ * used when setting a PGC_INTERNAL option.
  */
 typedef enum
 {
@@ -67,11 +77,35 @@ typedef enum
    PGC_S_ARGV = 3,             /* postmaster command line */
    PGC_S_DATABASE = 4,         /* per-database setting */
    PGC_S_USER = 5,             /* per-user setting */
-   PGC_S_CLIENT = 6,           /* from client (PGOPTIONS) */
+   PGC_S_CLIENT = 6,           /* from client connection request */
    PGC_S_OVERRIDE = 7,         /* special case to forcibly set default */
    PGC_S_SESSION = 8           /* SET command */
 } GucSource;
 
+
+/* GUC vars that are actually declared in guc.c, rather than elsewhere */
+extern bool log_statement;
+extern bool log_duration;
+extern bool Debug_print_plan;
+extern bool Debug_print_parse;
+extern bool Debug_print_rewritten;
+extern bool Debug_pretty_print;
+extern bool Explain_pretty_print;
+
+extern bool log_parser_stats;
+extern bool log_planner_stats;
+extern bool log_executor_stats;
+extern bool log_statement_stats;
+extern bool log_btree_build_stats;
+
+extern bool SQL_inheritance;
+extern bool Australian_timezones;
+
+extern int log_min_error_statement;
+extern int log_min_messages;
+extern int client_min_messages;
+
+
 extern void SetConfigOption(const char *name, const char *value,
                GucContext context, GucSource source);
 extern const char *GetConfigOption(const char *name);
@@ -80,6 +114,7 @@ extern void ProcessConfigFile(GucContext context);
 extern void InitializeGUCOptions(void);
 extern void ResetAllOptions(void);
 extern void AtEOXact_GUC(bool isCommit);
+extern void BeginReportingGUCOptions(void);
 extern void ParseLongOption(const char *string, char **name, char **value);
 extern bool set_config_option(const char *name, const char *value,
                  GucContext context, GucSource source,
@@ -100,42 +135,4 @@ extern void ProcessGUCArray(ArrayType *array, GucSource source);
 extern ArrayType *GUCArrayAdd(ArrayType *array, const char *name, const char *value);
 extern ArrayType *GUCArrayDelete(ArrayType *array, const char *name);
 
-extern const char *assign_min_error_statement(const char *newval, bool doit,
-                          bool interactive);
-
-extern const char *assign_log_min_messages(const char *newval,
-                          bool doit, bool interactive);
-extern const char *assign_client_min_messages(const char *newval,
-                          bool doit, bool interactive);
-extern bool log_statement;
-extern bool log_duration;
-extern bool Debug_print_plan;
-extern bool Debug_print_parse;
-extern bool Debug_print_rewritten;
-extern bool Debug_pretty_print;
-
-extern bool log_parser_stats;
-extern bool log_planner_stats;
-extern bool log_executor_stats;
-extern bool log_statement_stats;
-extern bool log_btree_build_stats;
-
-extern bool Explain_pretty_print;
-
-extern bool SQL_inheritance;
-extern bool Australian_timezones;
-
-extern int log_min_error_statement;
-extern char *log_min_error_statement_str;
-extern const char log_min_error_statement_str_default[];
-
-extern int log_min_messages;
-extern char *log_min_messages_str;
-extern const char log_min_messages_str_default[];
-
-extern int client_min_messages;
-extern char *client_min_messages_str;
-
-extern const char client_min_messages_str_default[];
-
 #endif   /* GUC_H */
index a31f34d7a98fa8d33f32a5039c41d3dd1bed9cb9..e2df4de859a8021b8b146ad6e5f250fc7303f3e2 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.236 2003/04/25 01:24:00 momjian Exp $
+ *   $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.237 2003/04/25 19:45:09 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -174,8 +174,6 @@ static const struct EnvironmentOptions
 
 static int connectDBStart(PGconn *conn);
 static int connectDBComplete(PGconn *conn);
-static bool PQsetenvStart(PGconn *conn);
-static PostgresPollingStatusType PQsetenvPoll(PGconn *conn);
 static PGconn *makeEmptyPGconn(void);
 static void freePGconn(PGconn *conn);
 static void closePGconn(PGconn *conn);
@@ -1207,10 +1205,6 @@ PQconnectPoll(PGconn *conn)
        case CONNECTION_MADE:
            break;
 
-       case CONNECTION_SETENV:
-           /* We allow PQsetenvPoll to decide whether to proceed */
-           break;
-
        default:
            printfPQExpBuffer(&conn->errorMessage,
                              libpq_gettext(
@@ -1517,10 +1511,10 @@ keep_going:                     /* We will come back to here until there
                 * message indicates that startup is successful, but we
                 * might also get an Error message indicating failure.
                 * (Notice messages indicating nonfatal warnings are also
-                * allowed by the protocol, as is a BackendKeyData
-                * message.) Easiest way to handle this is to let
-                * PQgetResult() read the messages. We just have to fake
-                * it out about the state of the connection, by setting
+                * allowed by the protocol, as are ParameterStatus and
+                * BackendKeyData messages.) Easiest way to handle this is
+                * to let PQgetResult() read the messages. We just have to
+                * fake it out about the state of the connection, by setting
                 * asyncStatus = PGASYNC_BUSY (done above).
                 */
 
@@ -1554,44 +1548,11 @@ keep_going:                     /* We will come back to here until there
                }
 
                /*
-                * Post-connection housekeeping. Prepare to send
-                * environment variables to server.
+                * We are open for business!
                 */
-               if (!PQsetenvStart(conn))
-                   goto error_return;
-
-               conn->status = CONNECTION_SETENV;
-
-               goto keep_going;
-           }
-
-       case CONNECTION_SETENV:
-
-           /*
-            * We pretend that the connection is OK for the duration of
-            * these queries.
-            */
-           conn->status = CONNECTION_OK;
-
-           switch (PQsetenvPoll(conn))
-           {
-               case PGRES_POLLING_OK:  /* Success */
-                   conn->status = CONNECTION_OK;
-                   return PGRES_POLLING_OK;
-
-               case PGRES_POLLING_READING:     /* Still going */
-                   conn->status = CONNECTION_SETENV;
-                   return PGRES_POLLING_READING;
-
-               case PGRES_POLLING_WRITING:     /* Still going */
-                   conn->status = CONNECTION_SETENV;
-                   return PGRES_POLLING_WRITING;
-
-               default:
-                   conn->status = CONNECTION_SETENV;
-                   goto error_return;
+               conn->status = CONNECTION_OK;
+               return PGRES_POLLING_OK;
            }
-           /* Unreachable */
 
        default:
            printfPQExpBuffer(&conn->errorMessage,
@@ -1618,239 +1579,6 @@ error_return:
 }
 
 
-/*
- *     PQsetenvStart
- *
- * Starts the process of passing the values of a standard set of environment
- * variables to the backend.
- */
-static bool
-PQsetenvStart(PGconn *conn)
-{
-   if (conn == NULL ||
-       conn->status == CONNECTION_BAD ||
-       conn->setenv_state != SETENV_STATE_IDLE)
-       return false;
-
-   conn->setenv_state = SETENV_STATE_ENCODINGS_SEND;
-
-   return true;
-}
-
-/*
- *     PQsetenvPoll
- *
- * Polls the process of passing the values of a standard set of environment
- * variables to the backend.
- */
-static PostgresPollingStatusType
-PQsetenvPoll(PGconn *conn)
-{
-   PGresult   *res;
-
-   if (conn == NULL || conn->status == CONNECTION_BAD)
-       return PGRES_POLLING_FAILED;
-
-   /* Check whether there are any data for us */
-   switch (conn->setenv_state)
-   {
-           /* These are reading states */
-       case SETENV_STATE_ENCODINGS_WAIT:
-           {
-               /* Load waiting data */
-               int         n = pqReadData(conn);
-
-               if (n < 0)
-                   goto error_return;
-               if (n == 0)
-                   return PGRES_POLLING_READING;
-
-               break;
-           }
-
-           /* These are writing states, so we just proceed. */
-       case SETENV_STATE_ENCODINGS_SEND:
-           break;
-
-           /* Should we raise an error if called when not active? */
-       case SETENV_STATE_IDLE:
-           return PGRES_POLLING_OK;
-
-       default:
-           printfPQExpBuffer(&conn->errorMessage,
-                             libpq_gettext(
-                                           "invalid setenv state %c, "
-                            "probably indicative of memory corruption\n"
-                                           ),
-                             conn->setenv_state);
-           goto error_return;
-   }
-
-   /* We will loop here until there is nothing left to do in this call. */
-   for (;;)
-   {
-       switch (conn->setenv_state)
-       {
-           case SETENV_STATE_ENCODINGS_SEND:
-               {
-                   const char *env = getenv("PGCLIENTENCODING");
-
-                   if (!env || *env == '\0')
-                   {
-                       /*
-                        * PGCLIENTENCODING is not specified, so query
-                        * server for it.  We must use begin/commit in
-                        * case autocommit is off by default.
-                        */
-                       if (!PQsendQuery(conn, "begin; select pg_client_encoding(); commit"))
-                           goto error_return;
-
-                       conn->setenv_state = SETENV_STATE_ENCODINGS_WAIT;
-                       return PGRES_POLLING_READING;
-                   }
-                   else
-                   {
-                       /* otherwise set client encoding in pg_conn struct */
-                       int         encoding = pg_char_to_encoding(env);
-
-                       if (encoding < 0)
-                       {
-                           printfPQExpBuffer(&conn->errorMessage,
-                                             libpq_gettext("invalid encoding name in PGCLIENTENCODING: %s\n"),
-                                             env);
-                           goto error_return;
-                       }
-                       conn->client_encoding = encoding;
-
-                       /* Move on to setting the environment options */
-                       conn->setenv_state = SETENV_STATE_IDLE;
-                   }
-                   break;
-               }
-
-           case SETENV_STATE_ENCODINGS_WAIT:
-               {
-                   if (PQisBusy(conn))
-                       return PGRES_POLLING_READING;
-
-                   res = PQgetResult(conn);
-
-                   if (res)
-                   {
-                       if (PQresultStatus(res) == PGRES_TUPLES_OK)
-                       {
-                           /* set client encoding in pg_conn struct */
-                           char       *encoding;
-
-                           encoding = PQgetvalue(res, 0, 0);
-                           if (!encoding)      /* this should not happen */
-                               conn->client_encoding = PG_SQL_ASCII;
-                           else
-                               conn->client_encoding = pg_char_to_encoding(encoding);
-                       }
-                       else if (PQresultStatus(res) != PGRES_COMMAND_OK)
-                       {
-                           PQclear(res);
-                           goto error_return;
-                       }
-                       PQclear(res);
-                       /* Keep reading until PQgetResult returns NULL */
-                   }
-                   else
-                   {
-                       /*
-                        * NULL result indicates that the query is
-                        * finished
-                        */
-                       conn->setenv_state = SETENV_STATE_IDLE;
-                   }
-                   break;
-               }
-
-           case SETENV_STATE_IDLE:
-               return PGRES_POLLING_OK;
-
-           default:
-               printfPQExpBuffer(&conn->errorMessage,
-                                 libpq_gettext("invalid state %c, "
-                          "probably indicative of memory corruption\n"),
-                                 conn->setenv_state);
-               goto error_return;
-       }
-   }
-
-   /* Unreachable */
-
-error_return:
-   conn->setenv_state = SETENV_STATE_IDLE;
-   return PGRES_POLLING_FAILED;
-}
-
-
-#ifdef NOT_USED
-
-/*
- *     PQsetenv
- *
- * Passes the values of a standard set of environment variables to the
- * backend.
- *
- * Returns true on success, false on failure.
- *
- * This function used to be exported for no particularly good reason.
- * Since it's no longer used by libpq itself, let's try #ifdef'ing it out
- * and see if anyone complains.
- */
-static bool
-PQsetenv(PGconn *conn)
-{
-   PostgresPollingStatusType flag = PGRES_POLLING_WRITING;
-
-   if (!PQsetenvStart(conn))
-       return false;
-
-   for (;;)
-   {
-       /*
-        * Wait, if necessary.  Note that the initial state (just after
-        * PQsetenvStart) is to wait for the socket to select for writing.
-        */
-       switch (flag)
-       {
-           case PGRES_POLLING_OK:
-               return true;    /* success! */
-
-           case PGRES_POLLING_READING:
-               if (pqWait(1, 0, conn))
-               {
-                   conn->status = CONNECTION_BAD;
-                   return false;
-               }
-               break;
-
-           case PGRES_POLLING_WRITING:
-               if (pqWait(0, 1, conn))
-               {
-                   conn->status = CONNECTION_BAD;
-                   return false;
-               }
-               break;
-
-           default:
-               /* Just in case we failed to set it in PQsetenvPoll */
-               conn->status = CONNECTION_BAD;
-               return false;
-       }
-
-       /*
-        * Now try to advance the state machine.
-        */
-       flag = PQsetenvPoll(conn);
-   }
-}
-#endif   /* NOT_USED */
-
-
 /*
  * makeEmptyPGconn
  *  - create a PGconn data structure with (as yet) no interesting data
@@ -1869,7 +1597,6 @@ makeEmptyPGconn(void)
    conn->noticeHook = defaultNoticeProcessor;
    conn->status = CONNECTION_BAD;
    conn->asyncStatus = PGASYNC_IDLE;
-   conn->setenv_state = SETENV_STATE_IDLE;
    conn->notifyList = DLNewList();
    conn->sock = -1;
 #ifdef USE_SSL
index 84520987812e6e87147f0c49259028572850e139..53c4e2886225e7b6a1f3381ab9d77bec5c31fb0f 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.132 2003/04/25 01:24:00 momjian Exp $
+ *   $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.133 2003/04/25 19:45:09 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -21,6 +21,8 @@
 #include "libpq-fe.h"
 #include "libpq-int.h"
 
+#include "mb/pg_wchar.h"
+
 #ifdef WIN32
 #include "win32.h"
 #else
@@ -54,6 +56,7 @@ static void handleSendFailure(PGconn *conn);
 static void handleSyncLoss(PGconn *conn, char id, int msgLength);
 static int getRowDescriptions(PGconn *conn);
 static int getAnotherTuple(PGconn *conn, int binary);
+static int getParameterStatus(PGconn *conn);
 static int getNotify(PGconn *conn);
 
 /* ---------------
@@ -950,6 +953,11 @@ parseInput(PGconn *conn)
         *
         * However, if the state is IDLE then we got trouble; we need to deal
         * with the unexpected message somehow.
+        *
+        * ParameterStatus ('S') messages are a special case: in IDLE state
+        * we must process 'em (this case could happen if a new value was
+        * adopted from config file due to SIGHUP), but otherwise we hold
+        * off until BUSY state.
         */
        if (id == 'A')
        {
@@ -970,6 +978,7 @@ parseInput(PGconn *conn)
            /*
             * Unexpected message in IDLE state; need to recover somehow.
             * ERROR messages are displayed using the notice processor;
+            * ParameterStatus is handled normally;
             * anything else is just dropped on the floor after displaying
             * a suitable warning notice.  (An ERROR is very possibly the
             * backend telling us why it is about to close the connection,
@@ -980,6 +989,11 @@ parseInput(PGconn *conn)
                if (pqGetErrorNotice(conn, false /* treat as notice */))
                    return;
            }
+           else if (id == 'S')
+           {
+               if (getParameterStatus(conn))
+                   return;
+           }
            else
            {
                snprintf(noticeWorkspace, sizeof(noticeWorkspace),
@@ -1021,6 +1035,10 @@ parseInput(PGconn *conn)
                                                      PGRES_EMPTY_QUERY);
                    conn->asyncStatus = PGASYNC_READY;
                    break;
+               case 'S':       /* parameter status */
+                   if (getParameterStatus(conn))
+                       return;
+                   break;
                case 'K':       /* secret key data from the backend */
 
                    /*
@@ -1671,6 +1689,35 @@ fail:
    return EOF;
 }
 
+/*
+ * Attempt to read a ParameterStatus message.
+ * This is possible in several places, so we break it out as a subroutine.
+ * Entry: 'S' message type and length have already been consumed.
+ * Exit: returns 0 if successfully consumed message.
+ *      returns EOF if not enough data.
+ */
+static int
+getParameterStatus(PGconn *conn)
+{
+   /* Get the parameter name */
+   if (pqGets(&conn->workBuffer, conn))
+       return EOF;
+   /* Is it one we care about? */
+   if (strcmp(conn->workBuffer.data, "client_encoding") == 0)
+   {
+       if (pqGets(&conn->workBuffer, conn))
+           return EOF;
+       conn->client_encoding = pg_char_to_encoding(conn->workBuffer.data);
+   }
+   else
+   {
+       /* Uninteresting parameter, ignore it */
+       if (pqGets(&conn->workBuffer, conn))
+           return EOF;
+   }
+   return 0;
+}
+
 /*
  * Attempt to read a Notify response message.
  * This is possible in several places, so we break it out as a subroutine.
@@ -2249,6 +2296,10 @@ PQfn(PGconn *conn,
                if (conn->result)
                    return prepareAsyncResult(conn);
                return PQmakeEmptyPGresult(conn, status);
+           case 'S':           /* parameter status */
+               if (getParameterStatus(conn))
+                   continue;
+               break;
            default:
                /* The backend violates the protocol. */
                printfPQExpBuffer(&conn->errorMessage,
index 4688fbf8f5aaef7e30f47235f185c4a281b01c6c..12670f3a0a4e694e22e3ce24de7ac87f47ea865d 100644 (file)
@@ -12,7 +12,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: libpq-int.h,v 1.64 2003/04/24 21:16:44 tgl Exp $
+ * $Id: libpq-int.h,v 1.65 2003/04/25 19:45:10 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -56,7 +56,7 @@ typedef int ssize_t;          /* ssize_t doesn't exist in VC (atleast
  * pqcomm.h describe what the backend knows, not what libpq knows.
  */
 
-#define PG_PROTOCOL_LIBPQ  PG_PROTOCOL(3,103) /* XXX temporary value */
+#define PG_PROTOCOL_LIBPQ  PG_PROTOCOL(3,104) /* XXX temporary value */
 
 /*
  * POSTGRES backend dependent Constants.
@@ -194,14 +194,6 @@ typedef enum
    PGASYNC_COPY_OUT            /* Copy Out data transfer in progress */
 }  PGAsyncStatusType;
 
-/* PGSetenvStatusType defines the state of the PQSetenv state machine */
-typedef enum
-{
-   SETENV_STATE_ENCODINGS_SEND,    /* About to send an "encodings" query */
-   SETENV_STATE_ENCODINGS_WAIT,    /* Waiting for query to complete      */
-   SETENV_STATE_IDLE
-}  PGSetenvStatusType;
-
 /* large-object-access data ... allocated only if large-object code is used. */
 typedef struct pgLobjfuncs
 {
@@ -293,9 +285,6 @@ struct pg_conn
    PGresult   *result;         /* result being constructed */
    PGresAttValue *curTuple;    /* tuple currently being read */
 
-   /* Status for sending environment info.  Used during PQSetenv only. */
-   PGSetenvStatusType setenv_state;
-
 #ifdef USE_SSL
    bool        allow_ssl_try;  /* Allowed to try SSL negotiation */
    bool        require_ssl;    /* Require SSL to make connection */