00001
00002
00003
00004
00005
00006
00007
00008
00009 #include "postgres.h"
00010
00011 #include "access/xact.h"
00012 #include "catalog/namespace.h"
00013 #include "mb/pg_wchar.h"
00014 #include "utils/builtins.h"
00015 #include "utils/memutils.h"
00016 #include "utils/syscache.h"
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #define MAX_CONVERSION_GROWTH 4
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 typedef struct ConvProcInfo
00039 {
00040 int s_encoding;
00041 int c_encoding;
00042 FmgrInfo to_server_info;
00043 FmgrInfo to_client_info;
00044 } ConvProcInfo;
00045
00046 static List *ConvProcList = NIL;
00047
00048
00049
00050
00051
00052 static FmgrInfo *ToServerConvProc = NULL;
00053 static FmgrInfo *ToClientConvProc = NULL;
00054
00055
00056
00057
00058 static pg_enc2name *ClientEncoding = &pg_enc2name_tbl[PG_SQL_ASCII];
00059 static pg_enc2name *DatabaseEncoding = &pg_enc2name_tbl[PG_SQL_ASCII];
00060 static pg_enc2name *PlatformEncoding = NULL;
00061
00062
00063
00064
00065
00066
00067
00068 static bool backend_startup_complete = false;
00069 static int pending_client_encoding = PG_SQL_ASCII;
00070
00071
00072
00073 static char *perform_default_encoding_conversion(const char *src,
00074 int len, bool is_client_to_server);
00075 static int cliplen(const char *str, int len, int limit);
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087 int
00088 PrepareClientEncoding(int encoding)
00089 {
00090 int current_server_encoding;
00091 ListCell *lc;
00092
00093 if (!PG_VALID_FE_ENCODING(encoding))
00094 return -1;
00095
00096
00097 if (!backend_startup_complete)
00098 return 0;
00099
00100 current_server_encoding = GetDatabaseEncoding();
00101
00102
00103
00104
00105 if (current_server_encoding == encoding ||
00106 current_server_encoding == PG_SQL_ASCII ||
00107 encoding == PG_SQL_ASCII)
00108 return 0;
00109
00110 if (IsTransactionState())
00111 {
00112
00113
00114
00115
00116
00117
00118 Oid to_server_proc,
00119 to_client_proc;
00120 ConvProcInfo *convinfo;
00121 MemoryContext oldcontext;
00122
00123 to_server_proc = FindDefaultConversionProc(encoding,
00124 current_server_encoding);
00125 if (!OidIsValid(to_server_proc))
00126 return -1;
00127 to_client_proc = FindDefaultConversionProc(current_server_encoding,
00128 encoding);
00129 if (!OidIsValid(to_client_proc))
00130 return -1;
00131
00132
00133
00134
00135 convinfo = (ConvProcInfo *) MemoryContextAlloc(TopMemoryContext,
00136 sizeof(ConvProcInfo));
00137 convinfo->s_encoding = current_server_encoding;
00138 convinfo->c_encoding = encoding;
00139 fmgr_info_cxt(to_server_proc, &convinfo->to_server_info,
00140 TopMemoryContext);
00141 fmgr_info_cxt(to_client_proc, &convinfo->to_client_info,
00142 TopMemoryContext);
00143
00144
00145 oldcontext = MemoryContextSwitchTo(TopMemoryContext);
00146 ConvProcList = lcons(convinfo, ConvProcList);
00147 MemoryContextSwitchTo(oldcontext);
00148
00149
00150
00151
00152
00153
00154 return 0;
00155 }
00156 else
00157 {
00158
00159
00160
00161
00162
00163
00164
00165
00166 foreach(lc, ConvProcList)
00167 {
00168 ConvProcInfo *oldinfo = (ConvProcInfo *) lfirst(lc);
00169
00170 if (oldinfo->s_encoding == current_server_encoding &&
00171 oldinfo->c_encoding == encoding)
00172 return 0;
00173 }
00174
00175 return -1;
00176 }
00177 }
00178
00179
00180
00181
00182
00183
00184
00185 int
00186 SetClientEncoding(int encoding)
00187 {
00188 int current_server_encoding;
00189 bool found;
00190 ListCell *lc;
00191 ListCell *prev;
00192 ListCell *next;
00193
00194 if (!PG_VALID_FE_ENCODING(encoding))
00195 return -1;
00196
00197
00198 if (!backend_startup_complete)
00199 {
00200 pending_client_encoding = encoding;
00201 return 0;
00202 }
00203
00204 current_server_encoding = GetDatabaseEncoding();
00205
00206
00207
00208
00209 if (current_server_encoding == encoding ||
00210 current_server_encoding == PG_SQL_ASCII ||
00211 encoding == PG_SQL_ASCII)
00212 {
00213 ClientEncoding = &pg_enc2name_tbl[encoding];
00214 ToServerConvProc = NULL;
00215 ToClientConvProc = NULL;
00216 return 0;
00217 }
00218
00219
00220
00221
00222
00223
00224
00225 found = false;
00226 prev = NULL;
00227 for (lc = list_head(ConvProcList); lc; lc = next)
00228 {
00229 ConvProcInfo *convinfo = (ConvProcInfo *) lfirst(lc);
00230
00231 next = lnext(lc);
00232
00233 if (convinfo->s_encoding == current_server_encoding &&
00234 convinfo->c_encoding == encoding)
00235 {
00236 if (!found)
00237 {
00238
00239 ClientEncoding = &pg_enc2name_tbl[encoding];
00240 ToServerConvProc = &convinfo->to_server_info;
00241 ToClientConvProc = &convinfo->to_client_info;
00242 found = true;
00243 }
00244 else
00245 {
00246
00247 ConvProcList = list_delete_cell(ConvProcList, lc, prev);
00248 pfree(convinfo);
00249 continue;
00250 }
00251 }
00252
00253 prev = lc;
00254 }
00255
00256 if (found)
00257 return 0;
00258 else
00259 return -1;
00260 }
00261
00262
00263
00264
00265
00266 void
00267 InitializeClientEncoding(void)
00268 {
00269 Assert(!backend_startup_complete);
00270 backend_startup_complete = true;
00271
00272 if (PrepareClientEncoding(pending_client_encoding) < 0 ||
00273 SetClientEncoding(pending_client_encoding) < 0)
00274 {
00275
00276
00277
00278
00279 ereport(FATAL,
00280 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
00281 errmsg("conversion between %s and %s is not supported",
00282 pg_enc2name_tbl[pending_client_encoding].name,
00283 GetDatabaseEncodingName())));
00284 }
00285 }
00286
00287
00288
00289
00290 int
00291 pg_get_client_encoding(void)
00292 {
00293 Assert(ClientEncoding);
00294 return ClientEncoding->encoding;
00295 }
00296
00297
00298
00299
00300 const char *
00301 pg_get_client_encoding_name(void)
00302 {
00303 Assert(ClientEncoding);
00304 return ClientEncoding->name;
00305 }
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327 unsigned char *
00328 pg_do_encoding_conversion(unsigned char *src, int len,
00329 int src_encoding, int dest_encoding)
00330 {
00331 unsigned char *result;
00332 Oid proc;
00333
00334 if (!IsTransactionState())
00335 return src;
00336
00337 if (src_encoding == dest_encoding)
00338 return src;
00339
00340 if (src_encoding == PG_SQL_ASCII || dest_encoding == PG_SQL_ASCII)
00341 return src;
00342
00343 if (len <= 0)
00344 return src;
00345
00346 proc = FindDefaultConversionProc(src_encoding, dest_encoding);
00347 if (!OidIsValid(proc))
00348 {
00349 ereport(LOG,
00350 (errcode(ERRCODE_UNDEFINED_FUNCTION),
00351 errmsg("default conversion function for encoding \"%s\" to \"%s\" does not exist",
00352 pg_encoding_to_char(src_encoding),
00353 pg_encoding_to_char(dest_encoding))));
00354 return src;
00355 }
00356
00357
00358
00359
00360
00361
00362 if (!SearchSysCacheExists1(PROCOID, ObjectIdGetDatum(proc)))
00363 {
00364 elog(LOG, "cache lookup failed for function %u", proc);
00365 return src;
00366 }
00367
00368
00369
00370
00371 if ((Size) len >= (MaxAllocSize / (Size) MAX_CONVERSION_GROWTH))
00372 ereport(ERROR,
00373 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
00374 errmsg("out of memory"),
00375 errdetail("String of %d bytes is too long for encoding conversion.",
00376 len)));
00377
00378 result = palloc(len * MAX_CONVERSION_GROWTH + 1);
00379
00380 OidFunctionCall5(proc,
00381 Int32GetDatum(src_encoding),
00382 Int32GetDatum(dest_encoding),
00383 CStringGetDatum(src),
00384 CStringGetDatum(result),
00385 Int32GetDatum(len));
00386 return result;
00387 }
00388
00389
00390
00391
00392
00393
00394 Datum
00395 pg_convert_to(PG_FUNCTION_ARGS)
00396 {
00397 Datum string = PG_GETARG_DATUM(0);
00398 Datum dest_encoding_name = PG_GETARG_DATUM(1);
00399 Datum src_encoding_name = DirectFunctionCall1(namein,
00400 CStringGetDatum(DatabaseEncoding->name));
00401 Datum result;
00402
00403
00404
00405
00406
00407
00408 result = DirectFunctionCall3(pg_convert, string,
00409 src_encoding_name, dest_encoding_name);
00410
00411 PG_RETURN_DATUM(result);
00412 }
00413
00414
00415
00416
00417
00418
00419 Datum
00420 pg_convert_from(PG_FUNCTION_ARGS)
00421 {
00422 Datum string = PG_GETARG_DATUM(0);
00423 Datum src_encoding_name = PG_GETARG_DATUM(1);
00424 Datum dest_encoding_name = DirectFunctionCall1(namein,
00425 CStringGetDatum(DatabaseEncoding->name));
00426 Datum result;
00427
00428 result = DirectFunctionCall3(pg_convert, string,
00429 src_encoding_name, dest_encoding_name);
00430
00431
00432
00433
00434
00435
00436
00437
00438 PG_RETURN_DATUM(result);
00439 }
00440
00441
00442
00443
00444
00445
00446 Datum
00447 pg_convert(PG_FUNCTION_ARGS)
00448 {
00449 bytea *string = PG_GETARG_BYTEA_PP(0);
00450 char *src_encoding_name = NameStr(*PG_GETARG_NAME(1));
00451 int src_encoding = pg_char_to_encoding(src_encoding_name);
00452 char *dest_encoding_name = NameStr(*PG_GETARG_NAME(2));
00453 int dest_encoding = pg_char_to_encoding(dest_encoding_name);
00454 const char *src_str;
00455 char *dest_str;
00456 bytea *retval;
00457 int len;
00458
00459 if (src_encoding < 0)
00460 ereport(ERROR,
00461 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
00462 errmsg("invalid source encoding name \"%s\"",
00463 src_encoding_name)));
00464 if (dest_encoding < 0)
00465 ereport(ERROR,
00466 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
00467 errmsg("invalid destination encoding name \"%s\"",
00468 dest_encoding_name)));
00469
00470
00471 len = VARSIZE_ANY_EXHDR(string);
00472 src_str = VARDATA_ANY(string);
00473 pg_verify_mbstr_len(src_encoding, src_str, len, false);
00474
00475 dest_str = (char *) pg_do_encoding_conversion(
00476 (unsigned char *) src_str, len, src_encoding, dest_encoding);
00477 if (dest_str != src_str)
00478 len = strlen(dest_str);
00479
00480
00481
00482
00483 retval = (bytea *) palloc(len + VARHDRSZ);
00484 SET_VARSIZE(retval, len + VARHDRSZ);
00485 memcpy(VARDATA(retval), dest_str, len);
00486
00487 if (dest_str != src_str)
00488 pfree(dest_str);
00489
00490
00491 PG_FREE_IF_COPY(string, 0);
00492
00493 PG_RETURN_BYTEA_P(retval);
00494 }
00495
00496
00497
00498
00499
00500
00501
00502
00503 Datum
00504 length_in_encoding(PG_FUNCTION_ARGS)
00505 {
00506 bytea *string = PG_GETARG_BYTEA_P(0);
00507 char *src_encoding_name = NameStr(*PG_GETARG_NAME(1));
00508 int src_encoding = pg_char_to_encoding(src_encoding_name);
00509 int len = VARSIZE(string) - VARHDRSZ;
00510 int retval;
00511
00512 if (src_encoding < 0)
00513 ereport(ERROR,
00514 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
00515 errmsg("invalid encoding name \"%s\"",
00516 src_encoding_name)));
00517
00518 retval = pg_verify_mbstr_len(src_encoding, VARDATA(string), len, false);
00519 PG_RETURN_INT32(retval);
00520
00521 }
00522
00523 Datum
00524 pg_encoding_max_length_sql(PG_FUNCTION_ARGS)
00525 {
00526 int encoding = PG_GETARG_INT32(0);
00527
00528 if (PG_VALID_ENCODING(encoding))
00529 PG_RETURN_INT32(pg_wchar_table[encoding].maxmblen);
00530 else
00531 PG_RETURN_NULL();
00532 }
00533
00534
00535
00536
00537 char *
00538 pg_client_to_server(const char *s, int len)
00539 {
00540 Assert(ClientEncoding);
00541
00542 return pg_any_to_server(s, len, ClientEncoding->encoding);
00543 }
00544
00545
00546
00547
00548 char *
00549 pg_any_to_server(const char *s, int len, int encoding)
00550 {
00551 Assert(DatabaseEncoding);
00552 Assert(ClientEncoding);
00553
00554 if (len <= 0)
00555 return (char *) s;
00556
00557 if (encoding == DatabaseEncoding->encoding ||
00558 encoding == PG_SQL_ASCII)
00559 {
00560
00561
00562
00563 (void) pg_verify_mbstr(DatabaseEncoding->encoding, s, len, false);
00564 return (char *) s;
00565 }
00566
00567 if (DatabaseEncoding->encoding == PG_SQL_ASCII)
00568 {
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578 if (PG_VALID_BE_ENCODING(encoding))
00579 (void) pg_verify_mbstr(encoding, s, len, false);
00580 else
00581 {
00582 int i;
00583
00584 for (i = 0; i < len; i++)
00585 {
00586 if (s[i] == '\0' || IS_HIGHBIT_SET(s[i]))
00587 ereport(ERROR,
00588 (errcode(ERRCODE_CHARACTER_NOT_IN_REPERTOIRE),
00589 errmsg("invalid byte value for encoding \"%s\": 0x%02x",
00590 pg_enc2name_tbl[PG_SQL_ASCII].name,
00591 (unsigned char) s[i])));
00592 }
00593 }
00594 return (char *) s;
00595 }
00596
00597 if (ClientEncoding->encoding == encoding)
00598 return perform_default_encoding_conversion(s, len, true);
00599 else
00600 return (char *) pg_do_encoding_conversion(
00601 (unsigned char *) s, len, encoding, DatabaseEncoding->encoding);
00602 }
00603
00604
00605
00606
00607 char *
00608 pg_server_to_client(const char *s, int len)
00609 {
00610 Assert(ClientEncoding);
00611
00612 return pg_server_to_any(s, len, ClientEncoding->encoding);
00613 }
00614
00615
00616
00617
00618 char *
00619 pg_server_to_any(const char *s, int len, int encoding)
00620 {
00621 Assert(DatabaseEncoding);
00622 Assert(ClientEncoding);
00623
00624 if (len <= 0)
00625 return (char *) s;
00626
00627 if (encoding == DatabaseEncoding->encoding ||
00628 encoding == PG_SQL_ASCII ||
00629 DatabaseEncoding->encoding == PG_SQL_ASCII)
00630 return (char *) s;
00631
00632 if (ClientEncoding->encoding == encoding)
00633 return perform_default_encoding_conversion(s, len, false);
00634 else
00635 return (char *) pg_do_encoding_conversion(
00636 (unsigned char *) s, len, DatabaseEncoding->encoding, encoding);
00637 }
00638
00639
00640
00641
00642
00643
00644
00645 static char *
00646 perform_default_encoding_conversion(const char *src, int len, bool is_client_to_server)
00647 {
00648 char *result;
00649 int src_encoding,
00650 dest_encoding;
00651 FmgrInfo *flinfo;
00652
00653 if (is_client_to_server)
00654 {
00655 src_encoding = ClientEncoding->encoding;
00656 dest_encoding = DatabaseEncoding->encoding;
00657 flinfo = ToServerConvProc;
00658 }
00659 else
00660 {
00661 src_encoding = DatabaseEncoding->encoding;
00662 dest_encoding = ClientEncoding->encoding;
00663 flinfo = ToClientConvProc;
00664 }
00665
00666 if (flinfo == NULL)
00667 return (char *) src;
00668
00669
00670
00671
00672 if ((Size) len >= (MaxAllocSize / (Size) MAX_CONVERSION_GROWTH))
00673 ereport(ERROR,
00674 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
00675 errmsg("out of memory"),
00676 errdetail("String of %d bytes is too long for encoding conversion.",
00677 len)));
00678
00679 result = palloc(len * MAX_CONVERSION_GROWTH + 1);
00680
00681 FunctionCall5(flinfo,
00682 Int32GetDatum(src_encoding),
00683 Int32GetDatum(dest_encoding),
00684 CStringGetDatum(src),
00685 CStringGetDatum(result),
00686 Int32GetDatum(len));
00687 return result;
00688 }
00689
00690
00691
00692 int
00693 pg_mb2wchar(const char *from, pg_wchar *to)
00694 {
00695 return (*pg_wchar_table[DatabaseEncoding->encoding].mb2wchar_with_len) ((const unsigned char *) from, to, strlen(from));
00696 }
00697
00698
00699 int
00700 pg_mb2wchar_with_len(const char *from, pg_wchar *to, int len)
00701 {
00702 return (*pg_wchar_table[DatabaseEncoding->encoding].mb2wchar_with_len) ((const unsigned char *) from, to, len);
00703 }
00704
00705
00706 int
00707 pg_encoding_mb2wchar_with_len(int encoding,
00708 const char *from, pg_wchar *to, int len)
00709 {
00710 return (*pg_wchar_table[encoding].mb2wchar_with_len) ((const unsigned char *) from, to, len);
00711 }
00712
00713
00714 int
00715 pg_wchar2mb(const pg_wchar *from, char *to)
00716 {
00717 return (*pg_wchar_table[DatabaseEncoding->encoding].wchar2mb_with_len) (from, (unsigned char *)to, pg_wchar_strlen(from));
00718 }
00719
00720
00721 int
00722 pg_wchar2mb_with_len(const pg_wchar *from, char *to, int len)
00723 {
00724 return (*pg_wchar_table[DatabaseEncoding->encoding].wchar2mb_with_len) (from, (unsigned char *)to, len);
00725 }
00726
00727
00728 int
00729 pg_encoding_wchar2mb_with_len(int encoding,
00730 const pg_wchar *from, char *to, int len)
00731 {
00732 return (*pg_wchar_table[encoding].wchar2mb_with_len) (from, (unsigned char *)to, len);
00733 }
00734
00735
00736 int
00737 pg_mblen(const char *mbstr)
00738 {
00739 return ((*pg_wchar_table[DatabaseEncoding->encoding].mblen) ((const unsigned char *) mbstr));
00740 }
00741
00742
00743 int
00744 pg_dsplen(const char *mbstr)
00745 {
00746 return ((*pg_wchar_table[DatabaseEncoding->encoding].dsplen) ((const unsigned char *) mbstr));
00747 }
00748
00749
00750 int
00751 pg_mbstrlen(const char *mbstr)
00752 {
00753 int len = 0;
00754
00755
00756 if (pg_database_encoding_max_length() == 1)
00757 return strlen(mbstr);
00758
00759 while (*mbstr)
00760 {
00761 mbstr += pg_mblen(mbstr);
00762 len++;
00763 }
00764 return len;
00765 }
00766
00767
00768
00769
00770 int
00771 pg_mbstrlen_with_len(const char *mbstr, int limit)
00772 {
00773 int len = 0;
00774
00775
00776 if (pg_database_encoding_max_length() == 1)
00777 return limit;
00778
00779 while (limit > 0 && *mbstr)
00780 {
00781 int l = pg_mblen(mbstr);
00782
00783 limit -= l;
00784 mbstr += l;
00785 len++;
00786 }
00787 return len;
00788 }
00789
00790
00791
00792
00793
00794
00795
00796 int
00797 pg_mbcliplen(const char *mbstr, int len, int limit)
00798 {
00799 return pg_encoding_mbcliplen(DatabaseEncoding->encoding, mbstr,
00800 len, limit);
00801 }
00802
00803
00804
00805
00806 int
00807 pg_encoding_mbcliplen(int encoding, const char *mbstr,
00808 int len, int limit)
00809 {
00810 mblen_converter mblen_fn;
00811 int clen = 0;
00812 int l;
00813
00814
00815 if (pg_encoding_max_length(encoding) == 1)
00816 return cliplen(mbstr, len, limit);
00817
00818 mblen_fn = pg_wchar_table[encoding].mblen;
00819
00820 while (len > 0 && *mbstr)
00821 {
00822 l = (*mblen_fn) ((const unsigned char *) mbstr);
00823 if ((clen + l) > limit)
00824 break;
00825 clen += l;
00826 if (clen == limit)
00827 break;
00828 len -= l;
00829 mbstr += l;
00830 }
00831 return clen;
00832 }
00833
00834
00835
00836
00837
00838 int
00839 pg_mbcharcliplen(const char *mbstr, int len, int limit)
00840 {
00841 int clen = 0;
00842 int nch = 0;
00843 int l;
00844
00845
00846 if (pg_database_encoding_max_length() == 1)
00847 return cliplen(mbstr, len, limit);
00848
00849 while (len > 0 && *mbstr)
00850 {
00851 l = pg_mblen(mbstr);
00852 nch++;
00853 if (nch > limit)
00854 break;
00855 clen += l;
00856 len -= l;
00857 mbstr += l;
00858 }
00859 return clen;
00860 }
00861
00862
00863 static int
00864 cliplen(const char *str, int len, int limit)
00865 {
00866 int l = 0;
00867
00868 len = Min(len, limit);
00869 while (l < len && str[l])
00870 l++;
00871 return l;
00872 }
00873
00874 void
00875 SetDatabaseEncoding(int encoding)
00876 {
00877 if (!PG_VALID_BE_ENCODING(encoding))
00878 elog(ERROR, "invalid database encoding: %d", encoding);
00879
00880 DatabaseEncoding = &pg_enc2name_tbl[encoding];
00881 Assert(DatabaseEncoding->encoding == encoding);
00882 }
00883
00884
00885
00886
00887 void
00888 pg_bind_textdomain_codeset(const char *domainname)
00889 {
00890 #if defined(ENABLE_NLS)
00891 int encoding = GetDatabaseEncoding();
00892 int i;
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904 #ifndef WIN32
00905 const char *ctype = setlocale(LC_CTYPE, NULL);
00906
00907 if (pg_strcasecmp(ctype, "C") != 0 && pg_strcasecmp(ctype, "POSIX") != 0)
00908 return;
00909 #endif
00910
00911 for (i = 0; pg_enc2gettext_tbl[i].name != NULL; i++)
00912 {
00913 if (pg_enc2gettext_tbl[i].encoding == encoding)
00914 {
00915 if (bind_textdomain_codeset(domainname,
00916 pg_enc2gettext_tbl[i].name) == NULL)
00917 elog(LOG, "bind_textdomain_codeset failed");
00918 break;
00919 }
00920 }
00921 #endif
00922 }
00923
00924 int
00925 GetDatabaseEncoding(void)
00926 {
00927 Assert(DatabaseEncoding);
00928 return DatabaseEncoding->encoding;
00929 }
00930
00931 const char *
00932 GetDatabaseEncodingName(void)
00933 {
00934 Assert(DatabaseEncoding);
00935 return DatabaseEncoding->name;
00936 }
00937
00938 Datum
00939 getdatabaseencoding(PG_FUNCTION_ARGS)
00940 {
00941 Assert(DatabaseEncoding);
00942 return DirectFunctionCall1(namein, CStringGetDatum(DatabaseEncoding->name));
00943 }
00944
00945 Datum
00946 pg_client_encoding(PG_FUNCTION_ARGS)
00947 {
00948 Assert(ClientEncoding);
00949 return DirectFunctionCall1(namein, CStringGetDatum(ClientEncoding->name));
00950 }
00951
00952 int
00953 GetPlatformEncoding(void)
00954 {
00955 if (PlatformEncoding == NULL)
00956 {
00957
00958 int encoding = pg_get_encoding_from_locale("", true);
00959
00960 if (encoding < 0)
00961 encoding = PG_SQL_ASCII;
00962 PlatformEncoding = &pg_enc2name_tbl[encoding];
00963 }
00964 return PlatformEncoding->encoding;
00965 }
00966
00967 #ifdef WIN32
00968
00969
00970
00971
00972
00973 WCHAR *
00974 pgwin32_toUTF16(const char *str, int len, int *utf16len)
00975 {
00976 WCHAR *utf16;
00977 int dstlen;
00978 UINT codepage;
00979
00980 codepage = pg_enc2name_tbl[GetDatabaseEncoding()].codepage;
00981
00982
00983
00984
00985
00986 if (codepage != 0)
00987 {
00988 utf16 = (WCHAR *) palloc(sizeof(WCHAR) * (len + 1));
00989 dstlen = MultiByteToWideChar(codepage, 0, str, len, utf16, len);
00990 utf16[dstlen] = (WCHAR) 0;
00991 }
00992 else
00993 {
00994 char *utf8;
00995
00996 utf8 = (char *) pg_do_encoding_conversion((unsigned char *) str,
00997 len, GetDatabaseEncoding(), PG_UTF8);
00998 if (utf8 != str)
00999 len = strlen(utf8);
01000
01001 utf16 = (WCHAR *) palloc(sizeof(WCHAR) * (len + 1));
01002 dstlen = MultiByteToWideChar(CP_UTF8, 0, utf8, len, utf16, len);
01003 utf16[dstlen] = (WCHAR) 0;
01004
01005 if (utf8 != str)
01006 pfree(utf8);
01007 }
01008
01009 if (dstlen == 0 && len > 0)
01010 {
01011 pfree(utf16);
01012 return NULL;
01013 }
01014
01015 if (utf16len)
01016 *utf16len = dstlen;
01017 return utf16;
01018 }
01019
01020 #endif