mirror of
https://github.com/postgres/postgres.git
synced 2025-04-29 13:56:47 +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:
parent
a2190c9eb6
commit
9cbaf72177
@ -1,4 +1,4 @@
|
||||
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/protocol.sgml,v 1.30 2003/04/24 21:16:42 tgl Exp $ -->
|
||||
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/protocol.sgml,v 1.31 2003/04/25 19:45:08 tgl Exp $ -->
|
||||
|
||||
<chapter id="protocol">
|
||||
<title>Frontend/Backend Protocol</title>
|
||||
@ -328,7 +328,7 @@
|
||||
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.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
@ -900,9 +900,9 @@
|
||||
<para>
|
||||
At present there is a hard-wired set of parameters for which
|
||||
ParameterStatus will be generated: they are
|
||||
<literal>version</> (backend version,
|
||||
a pseudo-parameter that cannot change after startup);
|
||||
<literal>database_encoding</> (also not presently changeable after start);
|
||||
<literal>server_version</> (a pseudo-parameter that cannot change after
|
||||
startup);
|
||||
<literal>server_encoding</> (also not presently changeable after start);
|
||||
<literal>client_encoding</>, and
|
||||
<literal>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.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The backend sends ParameterStatus ('<literal>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.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The CursorResponse ('<literal>P</>') message is no longer generated by
|
||||
the backend.
|
||||
|
@ -1,5 +1,5 @@
|
||||
<!--
|
||||
$Header: /cvsroot/pgsql/doc/src/sgml/ref/set.sgml,v 1.73 2003/03/25 16:15:44 petere Exp $
|
||||
$Header: /cvsroot/pgsql/doc/src/sgml/ref/set.sgml,v 1.74 2003/04/25 19:45:08 tgl Exp $
|
||||
PostgreSQL documentation
|
||||
-->
|
||||
|
||||
@ -52,7 +52,7 @@ SET [ SESSION | LOCAL ] TIME ZONE { <replaceable class="PARAMETER">timezone</rep
|
||||
<term><replaceable class="PARAMETER">variable</replaceable></term>
|
||||
<listitem>
|
||||
<para>
|
||||
A settable run-time parameter.
|
||||
Name of a settable run-time parameter.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
@ -79,8 +79,9 @@ SET [ SESSION | LOCAL ] TIME ZONE { <replaceable class="PARAMETER">timezone</rep
|
||||
|
||||
<para>
|
||||
The <command>SET</command> command changes run-time configuration
|
||||
parameters. Many of the run-time parameters listed in the
|
||||
<xref linkend="runtime-config"> can be changed on-the-fly with <command>SET</command>.
|
||||
parameters. Many of the run-time parameters listed in
|
||||
<xref linkend="runtime-config"> can be changed on-the-fly with
|
||||
<command>SET</command>.
|
||||
(But some require superuser privileges to change, and others cannot
|
||||
be changed after server or session start.) Note that
|
||||
<command>SET</command> only affects the value used by the current
|
||||
@ -123,7 +124,7 @@ SET [ SESSION | LOCAL ] TIME ZONE { <replaceable class="PARAMETER">timezone</rep
|
||||
<listitem>
|
||||
<para>
|
||||
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.
|
||||
</para>
|
||||
|
||||
@ -147,7 +148,7 @@ SET [ SESSION | LOCAL ] TIME ZONE { <replaceable class="PARAMETER">timezone</rep
|
||||
<para>
|
||||
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.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
@ -283,17 +284,6 @@ SELECT setseed(<replaceable>value</replaceable>);
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>SERVER_ENCODING</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Shows the server-side multibyte encoding. (At present, this
|
||||
parameter can be shown but not set, because the encoding is
|
||||
determined at <application>initdb</> time.)
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>TIME ZONE</term>
|
||||
<term>TIMEZONE</term>
|
||||
@ -410,7 +400,7 @@ SELECT setseed(<replaceable>value</replaceable>);
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><computeroutput>ERROR: '<replaceable>name</replaceable> is not a
|
||||
<term><computeroutput>ERROR: '<replaceable>name</replaceable>' is not a
|
||||
valid option name</computeroutput></term>
|
||||
<listitem>
|
||||
<para>
|
||||
@ -447,7 +437,7 @@ SELECT setseed(<replaceable>value</replaceable>);
|
||||
<title>Notes</title>
|
||||
|
||||
<para>
|
||||
The function <function>set_config</function> provides the equivalent
|
||||
The function <function>set_config</function> provides equivalent
|
||||
capability. See <xref linkend="functions-misc">.
|
||||
</para>
|
||||
</refsect1>
|
||||
@ -517,6 +507,8 @@ SELECT CURRENT_TIMESTAMP AS today;
|
||||
<title>See Also</title>
|
||||
|
||||
<simpara>
|
||||
<xref linkend="SQL-SHOW" endterm="SQL-SHOW-title">,
|
||||
<xref linkend="SQL-RESET" endterm="SQL-RESET-title">,
|
||||
<xref linkend="sql-set-constraints" endterm="sql-set-constraints-title">,
|
||||
<xref linkend="sql-set-session-authorization" endterm="sql-set-session-authorization-title">,
|
||||
<xref linkend="sql-set-transaction" endterm="sql-set-transaction-title">
|
||||
|
@ -1,5 +1,5 @@
|
||||
<!--
|
||||
$Header: /cvsroot/pgsql/doc/src/sgml/ref/show.sgml,v 1.24 2003/03/25 16:15:44 petere Exp $
|
||||
$Header: /cvsroot/pgsql/doc/src/sgml/ref/show.sgml,v 1.25 2003/04/25 19:45:08 tgl Exp $
|
||||
PostgreSQL documentation
|
||||
-->
|
||||
|
||||
@ -52,12 +52,13 @@ SHOW ALL
|
||||
<refsect1 id="R1-SQL-SHOW-1">
|
||||
<title>Description</title>
|
||||
<para>
|
||||
<command>SHOW</command> will display the current setting of a
|
||||
run-time parameter. These variables can be set using the
|
||||
<command>SHOW</command> will display the current setting of
|
||||
run-time parameters. These variables can be set using the
|
||||
<command>SET</command> statement, by editing the
|
||||
<filename>postgresql.conf</filename>, through the
|
||||
<envar>PGOPTIONS</envar> environmental variable, or through a
|
||||
command-line flag when starting the
|
||||
<filename>postgresql.conf</filename> configuration file, through the
|
||||
<envar>PGOPTIONS</envar> environmental variable (when using libpq
|
||||
or a libpq-based application), or through
|
||||
command-line flags when starting the
|
||||
<application>postmaster</application>.
|
||||
</para>
|
||||
|
||||
@ -66,6 +67,64 @@ SHOW ALL
|
||||
does not start a new transaction block. See the
|
||||
<varname>autocommit</> section in <xref linkend="runtime-config"> for details.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Available parameters are documented in
|
||||
<xref linkend="runtime-config"> and on the
|
||||
<xref linkend="SQL-SET" endterm="SQL-SET-title"> reference page.
|
||||
In addition, there are a few parameters that can be shown but not set:
|
||||
|
||||
<variablelist>
|
||||
|
||||
<varlistentry>
|
||||
<term>SERVER_VERSION</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Shows the server's version number.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>SERVER_ENCODING</term>
|
||||
<listitem>
|
||||
<para>
|
||||
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.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>LC_COLLATE</term>
|
||||
<listitem>
|
||||
<para>
|
||||
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 <application>initdb</> time.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>LC_CTYPE</term>
|
||||
<listitem>
|
||||
<para>
|
||||
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 <application>initdb</> time.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Use <xref linkend="SQL-SET" endterm="SQL-SET-title"> to set the value
|
||||
of settable parameters.
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
@ -79,7 +138,7 @@ SHOW ALL
|
||||
<listitem>
|
||||
<para>
|
||||
Message returned if <replaceable>name</replaceable> does
|
||||
not stand for an existing parameter.
|
||||
not stand for a known parameter.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
*
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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 <peter_e@gmx.net>.
|
||||
*
|
||||
* $Id: guc.h,v 1.27 2003/04/25 19:45:09 tgl Exp $
|
||||
*--------------------------------------------------------------------
|
||||
*/
|
||||
#ifndef GUC_H
|
||||
#define GUC_H
|
||||
@ -17,32 +21,37 @@
|
||||
* 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 */
|
||||
|
@ -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,45 +1548,12 @@ 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;
|
||||
conn->status = CONNECTION_OK;
|
||||
return PGRES_POLLING_OK;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
/* Unreachable */
|
||||
|
||||
default:
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
libpq_gettext(
|
||||
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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 */
|
||||
|
Loading…
x
Reference in New Issue
Block a user