freetds AT lists.ibiblio.org
Subject: FreeTDS Development Group
List archive
- From: Hi-Ho <jbaba AT amy.hi-ho.ne.jp>
- To: freetds AT lists.ibiblio.org
- Subject: [freetds] Internationalization of FreeTDS
- Date: Tue, 01 Jul 2003 13:09:43 +0900
I'm new here, so please excuse me if I'm missing something.
I am Japanese.
I think, the functions of ICONV of FreeTDS is wonderful!
But, there are several problems, to treat Japanese by using FreeTDS.
There are 2 facts.
(1) "server charset" is not necessarily "singlebyte".
(2) "server charset" and "client charset" are not necessarily same.
e.g.
Client charset = EUC-JP
Server charset = CP932
Of course, UCS2 is used with TDS7.0/8.0.
I present some patches.(base of freetds-0.62.dev.20030630)
I tested it by using MS SQLServer2000 by TDS4.2 and TDS7.0.
Please reflect it, if you are thought as usefulness.
Jiro Baba
diff -u -r freetds-0.62.dev.20030630/include/tds.h
freetds-0.62.dev.patch/include/tds.h
--- freetds-0.62.dev.20030630/include/tds.h 2003-06-25 06:07:14.000000000
+0900
+++ freetds-0.62.dev.patch/include/tds.h 2003-07-01 10:15:39.000000000 +0900
@@ -997,6 +997,8 @@
void tds_iconv_open(TDSSOCKET *tds, char *charset);
void tds_iconv_close(TDSSOCKET *tds);
void tds7_srv_charset_changed(TDSSOCKET * tds, int lcid);
+int tds_iconv_info_init(TDSICONVINFO * iconv_info, const char *client_name,
const char *server_name);
+int tds_charset_name_compare(const char *name1, const char *name2);
/* threadsafe.c */
char *tds_timestamp_str(char *str, int maxlen);
@@ -1151,6 +1153,8 @@
/** Calc a version number for Sybase. */
#define TDS_SYB_VER(maj,min,x) (((maj)<<24)|((min)<<16)|(x)<<8)
+#define IS_TDSENVCHARSET(x)
((x)->iconv_info[client2server_singlebyte].to_wire!=(iconv_t)-1)
+
#ifdef __cplusplus
}
#endif
diff -u -r freetds-0.62.dev.20030630/src/tds/iconv.c
freetds-0.62.dev.patch/src/tds/iconv.c
--- freetds-0.62.dev.20030630/src/tds/iconv.c 2003-06-10 16:22:24.000000000
+0900
+++ freetds-0.62.dev.patch/src/tds/iconv.c 2003-07-01 10:23:14.000000000
+0900
@@ -56,8 +56,6 @@
static int bytes_per_char(TDS_ENCODING * charset);
static const char *lcid2charset(int lcid);
static int skip_one_input_sequence(iconv_t cd, const TDS_ENCODING *
charset, ICONV_CONST char **input, size_t * input_size);
-static int tds_charset_name_compare(const char *name1, const char *name2);
-static int tds_iconv_info_init(TDSICONVINFO * iconv_info, const char
*client_name, const char *server_name);
static int tds_iconv_init(void);
static int tds_canonical_charset(const char *charset_name);
@@ -334,7 +332,7 @@
* \remarks The charset names written to \a iconv_info will be the
canonical names,
* not necessarily the names passed in.
*/
-static int
+int
tds_iconv_info_init(TDSICONVINFO * iconv_info, const char *client_name,
const char *server_name)
{
TDS_ENCODING *client = &iconv_info->client_charset;
@@ -815,7 +813,7 @@
* \returns strcmp(3) of the canonical names.
* \remarks If either name cannot be looked up, there is no way to return
an error.
*/
-static int
+int
tds_charset_name_compare(const char *name1, const char *name2)
{
const char *s1, *s2;
diff -u -r freetds-0.62.dev.20030630/src/tds/read.c
freetds-0.62.dev.patch/src/tds/read.c
--- freetds-0.62.dev.20030630/src/tds/read.c 2003-06-04 00:35:05.000000000
+0900
+++ freetds-0.62.dev.patch/src/tds/read.c 2003-07-01 10:28:55.000000000
+0900
@@ -263,7 +263,7 @@
tdsdump_log(TDS_DBG_NETWORK, "tds_get_string: need %d on wire for %d to
client?\n", dest_size, string_len);
- if (IS_TDS7_PLUS(tds)) {
+ if (IS_TDS7_PLUS(tds) || IS_TDSENVCHARSET(tds)) {
if (dest == NULL) {
tds_get_n(tds, NULL, wire_bytes);
TEMP_FREE;
@@ -283,8 +283,11 @@
/* convert chunk */
in_left = in_size;
+ if (IS_TDS7_PLUS(tds)) {
p += tds_iconv(to_client, tds->iconv_info, temp, &in_left, p, pend - p);
-
+ } else {
+ p += tds_iconv(to_client, &tds->iconv_info[client2server_singlebyte],
temp, &in_left, p, pend - p);
+ }
/* update for next chunk */
wire_bytes -= in_size - in_left;
if (in_left) {
@@ -364,7 +367,7 @@
* conversion descriptor. Then, with the metadata pre-established, we
just pass everything to
* tds_iconv and let it do the Right Thing.
*/
- if (curcol->column_size != curcol->on_server.column_size) { /* TODO:
remove this test */
+ if (curcol->column_size != curcol->on_server.column_size ||
IS_TDSENVCHARSET(tds)) { /* TODO: remove this test */
in_left = 0;
while (wire_size > 0) {
int in_size;
@@ -384,7 +387,11 @@
* TDS5/UTF-8 -> use server
* TDS5/UTF-16 -> use UTF-16
*/
+ if( IS_TDSENVCHARSET(tds) &&
is_ascii_type(curcol->on_server.column_type) ) {
+ p += tds_iconv(to_client, &tds->iconv_info[client2server_singlebyte],
temp, &in_left, p, pend - p);
+ } else {
p += tds_iconv(to_client, tds->iconv_info, temp, &in_left, p, pend - p);
+ }
wire_size -= in_size - in_left;
if (in_left) {
diff -u -r freetds-0.62.dev.20030630/src/tds/token.c
freetds-0.62.dev.patch/src/tds/token.c
--- freetds-0.62.dev.20030630/src/tds/token.c 2003-06-12 05:10:58.000000000
+0900
+++ freetds-0.62.dev.patch/src/tds/token.c 2003-07-01 10:21:43.000000000
+0900
@@ -2032,6 +2032,16 @@
free(newval);
}
+ switch (type) {
+ case TDS_ENV_CHARSET:
+ {
+ TDSICONVINFO *iconv_info = &tds->iconv_info[client2server_singlebyte];
+ if( tds_charset_name_compare(tds->iconv_info->client_charset.name,
tds->env->charset) != 0 ) {
+ tds_iconv_info_init(iconv_info, tds->iconv_info->client_charset.name,
tds->env->charset);
+ }
+ }
+ break;
+ }
return TDS_SUCCEED;
}
diff -u -r freetds-0.62.dev.20030630/src/tds/write.c
freetds-0.62.dev.patch/src/tds/write.c
--- freetds-0.62.dev.20030630/src/tds/write.c 2003-06-04 00:35:06.000000000
+0900
+++ freetds-0.62.dev.patch/src/tds/write.c 2003-07-01 10:31:23.000000000
+0900
@@ -141,12 +141,16 @@
assert(len >= 0);
- if (IS_TDS7_PLUS(tds)) {
+ if (IS_TDS7_PLUS(tds) || IS_TDSENVCHARSET(tds)) {
eob = s + len; /* 1 past the end of the input buffer */
while (len > 0) {
tdsdump_log(TDS_DBG_NETWORK, "%L tds_put_string converting %d bytes of
\"%s\"\n", len, s);
output_size = sizeof(buffer);
+ if(IS_TDS7_PLUS(tds)) {
bytes_out = tds_iconv(to_server, tds->iconv_info, s, &len, buffer,
output_size);
+ } else {
+ bytes_out = tds_iconv(to_server,
&tds->iconv_info[client2server_singlebyte], s, &len, buffer, output_size);
+ }
s = eob - len; /* len was reduced by number of bytes processed by
tds_iconv() */
tds_put_n(tds, buffer, bytes_out);
}
-
[freetds] Internationalization of FreeTDS,
Hi-Ho, 07/01/2003
- Re: [freetds] Internationalization of FreeTDS, James K. Lowden, 07/01/2003
- <Possible follow-up(s)>
- RE: [freetds] Internationalization of FreeTDS, Lowden, James K, 07/02/2003
Archive powered by MHonArc 2.6.24.