|
4 | 4 | * (currently mule internal code (mic) is used)
|
5 | 5 | * Tatsuo Ishii
|
6 | 6 | *
|
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 $ |
8 | 8 | */
|
9 | 9 | #include"postgres.h"
|
10 | 10 |
|
@@ -32,108 +32,149 @@ static pg_enc2name *DatabaseEncoding = &pg_enc2name_tbl[PG_SQL_ASCII];
|
32 | 32 | staticFmgrInfo*ToServerConvProc=NULL;
|
33 | 33 | staticFmgrInfo*ToClientConvProc=NULL;
|
34 | 34 |
|
| 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 | +staticboolbackend_startup_complete= false; |
| 42 | +staticintpending_client_encoding=PG_SQL_ASCII; |
| 43 | + |
| 44 | + |
35 | 45 | /* Internal functions */
|
36 | 46 | staticunsignedchar*perform_default_encoding_conversion(unsignedchar*src,
|
37 | 47 | intlen,boolis_client_to_server);
|
38 | 48 | staticintcliplen(constunsignedchar*str,intlen,intlimit);
|
39 | 49 |
|
40 |
| -/* Flag to we need to initialize client encoding info */ |
41 |
| -staticboolneed_to_init_client_encoding=-1; |
42 | 50 |
|
43 | 51 | /*
|
44 | 52 | * Set the client encoding and save fmgrinfo for the conversion
|
45 |
| - * function if necessary. ifencoding conversion between client/server |
46 |
| - *encoding is not supported, returns -1 |
47 |
| -*/ |
| 53 | + * function if necessary. Returns 0ifokay, -1 if not (bad encoding |
| 54 | + *or can't support conversion) |
| 55 | +*/ |
48 | 56 | int
|
49 | 57 | SetClientEncoding(intencoding,booldoit)
|
50 | 58 | {
|
51 | 59 | intcurrent_server_encoding;
|
52 | 60 | Oidto_server_proc,
|
53 | 61 | to_client_proc;
|
54 |
| -FmgrInfo*to_server=NULL; |
55 |
| -FmgrInfo*to_client=NULL; |
| 62 | +FmgrInfo*to_server; |
| 63 | +FmgrInfo*to_client; |
56 | 64 | MemoryContextoldcontext;
|
57 | 65 |
|
58 |
| -current_server_encoding=GetDatabaseEncoding(); |
59 |
| - |
60 | 66 | if (!PG_VALID_FE_ENCODING(encoding))
|
61 | 67 | return (-1);
|
62 | 68 |
|
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) |
72 | 71 | {
|
73 |
| -ClientEncoding=&pg_enc2name_tbl[encoding]; |
| 72 | +if (doit) |
| 73 | +pending_client_encoding=encoding; |
74 | 74 | return0;
|
75 | 75 | }
|
76 | 76 |
|
| 77 | +current_server_encoding=GetDatabaseEncoding(); |
| 78 | + |
77 | 79 | /*
|
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. |
80 | 81 | */
|
81 |
| -if (IsTransactionState()) |
| 82 | +if (current_server_encoding==encoding|| |
| 83 | +(current_server_encoding==PG_SQL_ASCII|| |
| 84 | +encoding==PG_SQL_ASCII)) |
82 | 85 | {
|
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 | +return0; |
99 | 107 | }
|
100 | 108 |
|
| 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 | + */ |
101 | 124 | if (!doit)
|
102 | 125 | return0;
|
103 | 126 |
|
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); |
107 | 137 |
|
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]; |
115 | 139 |
|
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); |
123 | 153 | }
|
| 154 | +ToClientConvProc=to_client; |
| 155 | + |
124 | 156 | return0;
|
125 | 157 | }
|
126 | 158 |
|
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. |
129 | 162 | */
|
130 | 163 | void
|
131 |
| -InitializeClientEncoding() |
| 164 | +InitializeClientEncoding(void) |
132 | 165 | {
|
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) |
134 | 170 | {
|
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()); |
137 | 178 | }
|
138 | 179 | }
|
139 | 180 |
|
|