|
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 |
|
|