* Set the active client encoding and set up the conversion-function pointers. * PrepareClientEncoding should have been called previously for this encoding. * * Returns 0 if okay, -1 if not (bad encoding or can't support conversion) */
| 207 | * Returns 0 if okay, -1 if not (bad encoding or can't support conversion) |
| 208 | */ |
| 209 | int |
| 210 | SetClientEncoding(int encoding) |
| 211 | { |
| 212 | int current_server_encoding; |
| 213 | bool found; |
| 214 | ListCell *lc; |
| 215 | |
| 216 | if (!PG_VALID_FE_ENCODING(encoding)) |
| 217 | return -1; |
| 218 | |
| 219 | /* Can't do anything during startup, per notes above */ |
| 220 | if (!backend_startup_complete) |
| 221 | { |
| 222 | pending_client_encoding = encoding; |
| 223 | return 0; |
| 224 | } |
| 225 | |
| 226 | current_server_encoding = GetDatabaseEncoding(); |
| 227 | |
| 228 | /* |
| 229 | * Check for cases that require no conversion function. |
| 230 | */ |
| 231 | if (current_server_encoding == encoding || |
| 232 | current_server_encoding == PG_SQL_ASCII || |
| 233 | encoding == PG_SQL_ASCII) |
| 234 | { |
| 235 | ClientEncoding = &pg_enc2name_tbl[encoding]; |
| 236 | ToServerConvProc = NULL; |
| 237 | ToClientConvProc = NULL; |
| 238 | return 0; |
| 239 | } |
| 240 | |
| 241 | /* |
| 242 | * Search the cache for the entry previously prepared by |
| 243 | * PrepareClientEncoding; if there isn't one, we lose. While at it, |
| 244 | * release any duplicate entries so that repeated Prepare/Set cycles don't |
| 245 | * leak memory. |
| 246 | */ |
| 247 | found = false; |
| 248 | foreach(lc, ConvProcList) |
| 249 | { |
| 250 | ConvProcInfo *convinfo = (ConvProcInfo *) lfirst(lc); |
| 251 | |
| 252 | if (convinfo->s_encoding == current_server_encoding && |
| 253 | convinfo->c_encoding == encoding) |
| 254 | { |
| 255 | if (!found) |
| 256 | { |
| 257 | /* Found newest entry, so set up */ |
| 258 | ClientEncoding = &pg_enc2name_tbl[encoding]; |
| 259 | ToServerConvProc = &convinfo->to_server_info; |
| 260 | ToClientConvProc = &convinfo->to_client_info; |
| 261 | found = true; |
| 262 | } |
| 263 | else |
| 264 | { |
| 265 | /* Duplicate entry, release it */ |
| 266 | ConvProcList = foreach_delete_current(ConvProcList, lc); |
no test coverage detected