Skip to content

Commit 5f15fa8

Browse files
committed
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.
1 parent 20aae30 commit 5f15fa8

File tree

2 files changed

+108
-67
lines changed

2 files changed

+108
-67
lines changed

src/backend/commands/variable.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
*
1010
*
1111
* IDENTIFICATION
12-
* $Header: /cvsroot/pgsql/src/backend/commands/variable.c,v 1.74 2003/04/25 19:45:08 tgl Exp $
12+
* $Header: /cvsroot/pgsql/src/backend/commands/variable.c,v 1.75 2003/04/27 17:31:25 tgl Exp $
1313
*
1414
*-------------------------------------------------------------------------
1515
*/
@@ -484,10 +484,10 @@ assign_client_encoding(const char *value, bool doit, bool interactive)
484484
return NULL;
485485

486486
/*
487-
* XXX SetClientEncoding depends on namespace functions which are not
488-
* available at startup time. So we accept requested client encoding
489-
* anyway which might not be valid (e.g. no conversion procs
490-
* available).
487+
* Note: if we are in startup phase then SetClientEncoding may not be
488+
* able to really set the encoding. In this case we will assume that
489+
* the encoding is okay, and InitializeClientEncoding() will fix things
490+
* once initialization is complete.
491491
*/
492492
if (SetClientEncoding(encoding, doit) < 0)
493493
{

src/backend/utils/mb/mbutils.c

Lines changed: 103 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* (currently mule internal code (mic) is used)
55
* Tatsuo Ishii
66
*
7-
* $Header: /cvsroot/pgsql/src/backend/utils/mb/mbutils.c,v 1.39 2003/03/10 22:28:18 tgl Exp $
7+
* $Header: /cvsroot/pgsql/src/backend/utils/mb/mbutils.c,v 1.40 2003/04/27 17:31:25 tgl Exp $
88
*/
99
#include "postgres.h"
1010

@@ -32,108 +32,149 @@ static pg_enc2name *DatabaseEncoding = &pg_enc2name_tbl[PG_SQL_ASCII];
3232
static FmgrInfo *ToServerConvProc = NULL;
3333
static FmgrInfo *ToClientConvProc = NULL;
3434

35+
/*
36+
* During backend startup we can't set client encoding because we (a)
37+
* can't look up the conversion functions, and (b) may not know the database
38+
* encoding yet either. So SetClientEncoding() just accepts anything and
39+
* remembers it for InitializeClientEncoding() to apply later.
40+
*/
41+
static bool backend_startup_complete = false;
42+
static int pending_client_encoding = PG_SQL_ASCII;
43+
44+
3545
/* Internal functions */
3646
static unsigned char *perform_default_encoding_conversion(unsigned char *src,
3747
int len, bool is_client_to_server);
3848
static int cliplen(const unsigned char *str, int len, int limit);
3949

40-
/* Flag to we need to initialize client encoding info */
41-
static bool need_to_init_client_encoding = -1;
4250

4351
/*
4452
* Set the client encoding and save fmgrinfo for the conversion
45-
* function if necessary. if encoding conversion between client/server
46-
* encoding is not supported, returns -1
47-
*/
53+
* function if necessary. Returns 0 if okay, -1 if not (bad encoding
54+
* or can't support conversion)
55+
*/
4856
int
4957
SetClientEncoding(int encoding, bool doit)
5058
{
5159
int current_server_encoding;
5260
Oid to_server_proc,
5361
to_client_proc;
54-
FmgrInfo *to_server = NULL;
55-
FmgrInfo *to_client = NULL;
62+
FmgrInfo *to_server;
63+
FmgrInfo *to_client;
5664
MemoryContext oldcontext;
5765

58-
current_server_encoding = GetDatabaseEncoding();
59-
6066
if (!PG_VALID_FE_ENCODING(encoding))
6167
return (-1);
6268

63-
/* If we cannot actually set client encoding info, remember it
64-
* so that we could set it using InitializeClientEncoding()
65-
* in InitPostgres()
66-
*/
67-
if (current_server_encoding != encoding && !IsTransactionState())
68-
need_to_init_client_encoding = encoding;
69-
70-
if (current_server_encoding == encoding ||
71-
(current_server_encoding == PG_SQL_ASCII || encoding == PG_SQL_ASCII))
69+
/* Can't do anything during startup, per notes above */
70+
if (!backend_startup_complete)
7271
{
73-
ClientEncoding = &pg_enc2name_tbl[encoding];
72+
if (doit)
73+
pending_client_encoding = encoding;
7474
return 0;
7575
}
7676

77+
current_server_encoding = GetDatabaseEncoding();
78+
7779
/*
78-
* XXX We cannot use FindDefaultConversionProc() while in bootstrap or
79-
* initprocessing mode since namespace functions will not work.
80+
* Check for cases that require no conversion function.
8081
*/
81-
if (IsTransactionState())
82+
if (current_server_encoding == encoding ||
83+
(current_server_encoding == PG_SQL_ASCII ||
84+
encoding == PG_SQL_ASCII))
8285
{
83-
to_server_proc = FindDefaultConversionProc(encoding, current_server_encoding);
84-
to_client_proc = FindDefaultConversionProc(current_server_encoding, encoding);
85-
86-
if (!OidIsValid(to_server_proc) || !OidIsValid(to_client_proc))
87-
return -1;
88-
89-
/*
90-
* load the fmgr info into TopMemoryContext so that it survives
91-
* outside transaction.
92-
*/
93-
oldcontext = MemoryContextSwitchTo(TopMemoryContext);
94-
to_server = palloc(sizeof(FmgrInfo));
95-
to_client = palloc(sizeof(FmgrInfo));
96-
fmgr_info(to_server_proc, to_server);
97-
fmgr_info(to_client_proc, to_client);
98-
MemoryContextSwitchTo(oldcontext);
86+
if (doit)
87+
{
88+
ClientEncoding = &pg_enc2name_tbl[encoding];
89+
90+
if (ToServerConvProc != NULL)
91+
{
92+
if (ToServerConvProc->fn_extra)
93+
pfree(ToServerConvProc->fn_extra);
94+
pfree(ToServerConvProc);
95+
}
96+
ToServerConvProc = NULL;
97+
98+
if (ToClientConvProc != NULL)
99+
{
100+
if (ToClientConvProc->fn_extra)
101+
pfree(ToClientConvProc->fn_extra);
102+
pfree(ToClientConvProc);
103+
}
104+
ToClientConvProc = NULL;
105+
}
106+
return 0;
99107
}
100108

109+
/*
110+
* Look up the conversion functions.
111+
*/
112+
to_server_proc = FindDefaultConversionProc(encoding,
113+
current_server_encoding);
114+
if (!OidIsValid(to_server_proc))
115+
return -1;
116+
to_client_proc = FindDefaultConversionProc(current_server_encoding,
117+
encoding);
118+
if (!OidIsValid(to_client_proc))
119+
return -1;
120+
121+
/*
122+
* Done if not wanting to actually apply setting.
123+
*/
101124
if (!doit)
102125
return 0;
103126

104-
if (IsTransactionState())
105-
{
106-
ClientEncoding = &pg_enc2name_tbl[encoding];
127+
/*
128+
* load the fmgr info into TopMemoryContext so that it survives
129+
* outside transaction.
130+
*/
131+
oldcontext = MemoryContextSwitchTo(TopMemoryContext);
132+
to_server = palloc(sizeof(FmgrInfo));
133+
to_client = palloc(sizeof(FmgrInfo));
134+
fmgr_info(to_server_proc, to_server);
135+
fmgr_info(to_client_proc, to_client);
136+
MemoryContextSwitchTo(oldcontext);
107137

108-
if (ToServerConvProc != NULL)
109-
{
110-
if (ToServerConvProc->fn_extra)
111-
pfree(ToServerConvProc->fn_extra);
112-
pfree(ToServerConvProc);
113-
}
114-
ToServerConvProc = to_server;
138+
ClientEncoding = &pg_enc2name_tbl[encoding];
115139

116-
if (ToClientConvProc != NULL)
117-
{
118-
if (ToClientConvProc->fn_extra)
119-
pfree(ToClientConvProc->fn_extra);
120-
pfree(ToClientConvProc);
121-
}
122-
ToClientConvProc = to_client;
140+
if (ToServerConvProc != NULL)
141+
{
142+
if (ToServerConvProc->fn_extra)
143+
pfree(ToServerConvProc->fn_extra);
144+
pfree(ToServerConvProc);
145+
}
146+
ToServerConvProc = to_server;
147+
148+
if (ToClientConvProc != NULL)
149+
{
150+
if (ToClientConvProc->fn_extra)
151+
pfree(ToClientConvProc->fn_extra);
152+
pfree(ToClientConvProc);
123153
}
154+
ToClientConvProc = to_client;
155+
124156
return 0;
125157
}
126158

127-
/* Initialize client encoding if necessary.
128-
* called from InitPostgres() once during backend starting up.
159+
/*
160+
* Initialize client encoding if necessary.
161+
* called from InitPostgres() once during backend starting up.
129162
*/
130163
void
131-
InitializeClientEncoding()
164+
InitializeClientEncoding(void)
132165
{
133-
if (need_to_init_client_encoding > 0)
166+
Assert(!backend_startup_complete);
167+
backend_startup_complete = true;
168+
169+
if (SetClientEncoding(pending_client_encoding, true) < 0)
134170
{
135-
SetClientEncoding(need_to_init_client_encoding, 1);
136-
need_to_init_client_encoding = -1;
171+
/*
172+
* Oops, the requested conversion is not available.
173+
* We couldn't fail before, but we can now.
174+
*/
175+
elog(FATAL, "Conversion between %s and %s is not supported",
176+
pg_enc2name_tbl[pending_client_encoding].name,
177+
GetDatabaseEncodingName());
137178
}
138179
}
139180

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy