mirror of
https://github.com/postgres/postgres.git
synced 2025-06-14 18:42:34 +03:00
Clean up some problems in SetClientEncoding: failed to honor doit flag
in all cases, leaked TopMemoryContext memory in others. Make the interaction between SetClientEncoding and InitializeClientEncoding cleaner and better documented. I suspect these changes should be back-patched into 7.3, but will wait on Tatsuo's verification.
This commit is contained in:
@ -9,7 +9,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/commands/variable.c,v 1.74 2003/04/25 19:45:08 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/commands/variable.c,v 1.75 2003/04/27 17:31:25 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -484,10 +484,10 @@ assign_client_encoding(const char *value, bool doit, bool interactive)
|
|||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* XXX SetClientEncoding depends on namespace functions which are not
|
* Note: if we are in startup phase then SetClientEncoding may not be
|
||||||
* available at startup time. So we accept requested client encoding
|
* able to really set the encoding. In this case we will assume that
|
||||||
* anyway which might not be valid (e.g. no conversion procs
|
* the encoding is okay, and InitializeClientEncoding() will fix things
|
||||||
* available).
|
* once initialization is complete.
|
||||||
*/
|
*/
|
||||||
if (SetClientEncoding(encoding, doit) < 0)
|
if (SetClientEncoding(encoding, doit) < 0)
|
||||||
{
|
{
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
* (currently mule internal code (mic) is used)
|
* (currently mule internal code (mic) is used)
|
||||||
* Tatsuo Ishii
|
* Tatsuo Ishii
|
||||||
*
|
*
|
||||||
* $Header: /cvsroot/pgsql/src/backend/utils/mb/mbutils.c,v 1.39 2003/03/10 22:28:18 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/utils/mb/mbutils.c,v 1.40 2003/04/27 17:31:25 tgl Exp $
|
||||||
*/
|
*/
|
||||||
#include "postgres.h"
|
#include "postgres.h"
|
||||||
|
|
||||||
@ -32,59 +32,97 @@ static pg_enc2name *DatabaseEncoding = &pg_enc2name_tbl[PG_SQL_ASCII];
|
|||||||
static FmgrInfo *ToServerConvProc = NULL;
|
static FmgrInfo *ToServerConvProc = NULL;
|
||||||
static FmgrInfo *ToClientConvProc = NULL;
|
static FmgrInfo *ToClientConvProc = NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* During backend startup we can't set client encoding because we (a)
|
||||||
|
* can't look up the conversion functions, and (b) may not know the database
|
||||||
|
* encoding yet either. So SetClientEncoding() just accepts anything and
|
||||||
|
* remembers it for InitializeClientEncoding() to apply later.
|
||||||
|
*/
|
||||||
|
static bool backend_startup_complete = false;
|
||||||
|
static int pending_client_encoding = PG_SQL_ASCII;
|
||||||
|
|
||||||
|
|
||||||
/* Internal functions */
|
/* Internal functions */
|
||||||
static unsigned char *perform_default_encoding_conversion(unsigned char *src,
|
static unsigned char *perform_default_encoding_conversion(unsigned char *src,
|
||||||
int len, bool is_client_to_server);
|
int len, bool is_client_to_server);
|
||||||
static int cliplen(const unsigned char *str, int len, int limit);
|
static int cliplen(const unsigned char *str, int len, int limit);
|
||||||
|
|
||||||
/* Flag to we need to initialize client encoding info */
|
|
||||||
static bool need_to_init_client_encoding = -1;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set the client encoding and save fmgrinfo for the conversion
|
* Set the client encoding and save fmgrinfo for the conversion
|
||||||
* function if necessary. if encoding conversion between client/server
|
* function if necessary. Returns 0 if okay, -1 if not (bad encoding
|
||||||
* encoding is not supported, returns -1
|
* or can't support conversion)
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
SetClientEncoding(int encoding, bool doit)
|
SetClientEncoding(int encoding, bool doit)
|
||||||
{
|
{
|
||||||
int current_server_encoding;
|
int current_server_encoding;
|
||||||
Oid to_server_proc,
|
Oid to_server_proc,
|
||||||
to_client_proc;
|
to_client_proc;
|
||||||
FmgrInfo *to_server = NULL;
|
FmgrInfo *to_server;
|
||||||
FmgrInfo *to_client = NULL;
|
FmgrInfo *to_client;
|
||||||
MemoryContext oldcontext;
|
MemoryContext oldcontext;
|
||||||
|
|
||||||
current_server_encoding = GetDatabaseEncoding();
|
|
||||||
|
|
||||||
if (!PG_VALID_FE_ENCODING(encoding))
|
if (!PG_VALID_FE_ENCODING(encoding))
|
||||||
return (-1);
|
return (-1);
|
||||||
|
|
||||||
/* If we cannot actually set client encoding info, remember it
|
/* Can't do anything during startup, per notes above */
|
||||||
* so that we could set it using InitializeClientEncoding()
|
if (!backend_startup_complete)
|
||||||
* in InitPostgres()
|
{
|
||||||
*/
|
if (doit)
|
||||||
if (current_server_encoding != encoding && !IsTransactionState())
|
pending_client_encoding = encoding;
|
||||||
need_to_init_client_encoding = encoding;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
current_server_encoding = GetDatabaseEncoding();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check for cases that require no conversion function.
|
||||||
|
*/
|
||||||
if (current_server_encoding == encoding ||
|
if (current_server_encoding == encoding ||
|
||||||
(current_server_encoding == PG_SQL_ASCII || encoding == PG_SQL_ASCII))
|
(current_server_encoding == PG_SQL_ASCII ||
|
||||||
|
encoding == PG_SQL_ASCII))
|
||||||
|
{
|
||||||
|
if (doit)
|
||||||
{
|
{
|
||||||
ClientEncoding = &pg_enc2name_tbl[encoding];
|
ClientEncoding = &pg_enc2name_tbl[encoding];
|
||||||
|
|
||||||
|
if (ToServerConvProc != NULL)
|
||||||
|
{
|
||||||
|
if (ToServerConvProc->fn_extra)
|
||||||
|
pfree(ToServerConvProc->fn_extra);
|
||||||
|
pfree(ToServerConvProc);
|
||||||
|
}
|
||||||
|
ToServerConvProc = NULL;
|
||||||
|
|
||||||
|
if (ToClientConvProc != NULL)
|
||||||
|
{
|
||||||
|
if (ToClientConvProc->fn_extra)
|
||||||
|
pfree(ToClientConvProc->fn_extra);
|
||||||
|
pfree(ToClientConvProc);
|
||||||
|
}
|
||||||
|
ToClientConvProc = NULL;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* XXX We cannot use FindDefaultConversionProc() while in bootstrap or
|
* Look up the conversion functions.
|
||||||
* initprocessing mode since namespace functions will not work.
|
|
||||||
*/
|
*/
|
||||||
if (IsTransactionState())
|
to_server_proc = FindDefaultConversionProc(encoding,
|
||||||
{
|
current_server_encoding);
|
||||||
to_server_proc = FindDefaultConversionProc(encoding, current_server_encoding);
|
if (!OidIsValid(to_server_proc))
|
||||||
to_client_proc = FindDefaultConversionProc(current_server_encoding, encoding);
|
|
||||||
|
|
||||||
if (!OidIsValid(to_server_proc) || !OidIsValid(to_client_proc))
|
|
||||||
return -1;
|
return -1;
|
||||||
|
to_client_proc = FindDefaultConversionProc(current_server_encoding,
|
||||||
|
encoding);
|
||||||
|
if (!OidIsValid(to_client_proc))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Done if not wanting to actually apply setting.
|
||||||
|
*/
|
||||||
|
if (!doit)
|
||||||
|
return 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* load the fmgr info into TopMemoryContext so that it survives
|
* load the fmgr info into TopMemoryContext so that it survives
|
||||||
@ -96,13 +134,7 @@ SetClientEncoding(int encoding, bool doit)
|
|||||||
fmgr_info(to_server_proc, to_server);
|
fmgr_info(to_server_proc, to_server);
|
||||||
fmgr_info(to_client_proc, to_client);
|
fmgr_info(to_client_proc, to_client);
|
||||||
MemoryContextSwitchTo(oldcontext);
|
MemoryContextSwitchTo(oldcontext);
|
||||||
}
|
|
||||||
|
|
||||||
if (!doit)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (IsTransactionState())
|
|
||||||
{
|
|
||||||
ClientEncoding = &pg_enc2name_tbl[encoding];
|
ClientEncoding = &pg_enc2name_tbl[encoding];
|
||||||
|
|
||||||
if (ToServerConvProc != NULL)
|
if (ToServerConvProc != NULL)
|
||||||
@ -120,20 +152,29 @@ SetClientEncoding(int encoding, bool doit)
|
|||||||
pfree(ToClientConvProc);
|
pfree(ToClientConvProc);
|
||||||
}
|
}
|
||||||
ToClientConvProc = to_client;
|
ToClientConvProc = to_client;
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize client encoding if necessary.
|
/*
|
||||||
|
* Initialize client encoding if necessary.
|
||||||
* called from InitPostgres() once during backend starting up.
|
* called from InitPostgres() once during backend starting up.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
InitializeClientEncoding()
|
InitializeClientEncoding(void)
|
||||||
{
|
{
|
||||||
if (need_to_init_client_encoding > 0)
|
Assert(!backend_startup_complete);
|
||||||
|
backend_startup_complete = true;
|
||||||
|
|
||||||
|
if (SetClientEncoding(pending_client_encoding, true) < 0)
|
||||||
{
|
{
|
||||||
SetClientEncoding(need_to_init_client_encoding, 1);
|
/*
|
||||||
need_to_init_client_encoding = -1;
|
* Oops, the requested conversion is not available.
|
||||||
|
* We couldn't fail before, but we can now.
|
||||||
|
*/
|
||||||
|
elog(FATAL, "Conversion between %s and %s is not supported",
|
||||||
|
pg_enc2name_tbl[pending_client_encoding].name,
|
||||||
|
GetDatabaseEncodingName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user