Skip to Content.
Sympa Menu

freetds - Re: [freetds] Read UNIVARCHAR field from Sybase 12.5.1

freetds AT lists.ibiblio.org

Subject: FreeTDS Development Group

List archive

Chronological Thread  
  • From: Alex Kiesel <kiesel AT schlund.de>
  • To: FreeTDS Development Group <freetds AT lists.ibiblio.org>
  • Subject: Re: [freetds] Read UNIVARCHAR field from Sybase 12.5.1
  • Date: Fri, 21 Nov 2003 11:44:25 +0100

On Nov 20, 2003, Thompson, Bill D (London) wrote:
> I see we have such a check in tds7_get_data_info()....i.e.
>
> if (is_blob_type(curcol->column_type)) {
> curcol->table_namelen =
> tds_get_string(tds, tds_get_smallint(tds), curcol->table_name,
> sizeof(curcol->table_name) - 1);
> }

Hi all,

thank you for your answers. I've been struggling with this for a while
now, and I think I've got a possible solution.

The attached patch adds support to properly read the univarchar data
from the wire and to handle it within the ctlib (I do not use or know
dblib).

One problem that I was unable to get rid of was that the data is - as it
seems - encoded with UTF-16. I think all that's missing is proper
curcol->iconv_info data for that column to automatically decode it, but
I did not get that right. Can someone here point me to the right
direction?

I am looking forward to any comments or advise :-)

Greets,
Alex

--
Alex Kiesel PGP Key: 0x09F4FA11
Index: include/cspublic.h
===================================================================
RCS file: /cvsroot/freetds/freetds/include/cspublic.h,v
retrieving revision 1.42
diff -u -r1.42 cspublic.h
--- include/cspublic.h 1 Nov 2003 23:02:07 -0000 1.42
+++ include/cspublic.h 21 Nov 2003 10:33:23 -0000
@@ -737,6 +737,7 @@
#define CS_VOID_TYPE 25
#define CS_USHORT_TYPE 26
#define CS_UNIQUE_TYPE 27
+#define CS_UNIVARCHAR_TYPE 28

/* cs_dt_info type values */
enum
Index: include/tds.h
===================================================================
RCS file: /cvsroot/freetds/freetds/include/tds.h,v
retrieving revision 1.154
diff -u -r1.154 tds.h
--- include/tds.h 16 Nov 2003 08:19:34 -0000 1.154
+++ include/tds.h 21 Nov 2003 10:33:23 -0000
@@ -413,8 +413,10 @@

SYBUNIQUE = 36, /* 0x24 */
#define SYBUNIQUE SYBUNIQUE
- SYBVARIANT = 98 /* 0x62 */
+ SYBVARIANT = 98, /* 0x62 */
#define SYBVARIANT SYBVARIANT
+ SYBUNIVARCHAR = -1001
+#define SYBUNIVARCHAR SYBUNIVARCHAR
} TDS_SERVER_TYPE;

#define SYBAOPCNT 0x4b
@@ -568,6 +570,7 @@
#define is_unicode_type(x) (x==XSYBNVARCHAR || x==XSYBNCHAR || x==SYBNTEXT)
#define is_collate_type(x) (x==XSYBVARCHAR || x==XSYBCHAR || x==SYBTEXT ||
x==XSYBNVARCHAR || x==XSYBNCHAR || x==SYBNTEXT)
#define is_ascii_type(x) ( x==XSYBCHAR || x==XSYBVARCHAR || x==SYBTEXT ||
x==SYBCHAR || x==SYBVARCHAR)
+#define is_binary_type(x) (x==SYBLONGBINARY)
#define is_char_type(x) (is_unicode_type(x) || is_ascii_type(x))
#define is_similar_type(x, y) ((is_char_type(x) && is_char_type(y)) ||
((is_unicode_type(x) && is_unicode_type(y))))

Index: src/ctlib/cs.c
===================================================================
RCS file: /cvsroot/freetds/freetds/src/ctlib/cs.c,v
retrieving revision 1.42
diff -u -r1.42 cs.c
--- src/ctlib/cs.c 1 Nov 2003 23:02:09 -0000 1.42
+++ src/ctlib/cs.c 21 Nov 2003 10:33:23 -0000
@@ -371,11 +371,13 @@
}
}
break;
+ case SYBUNIVARCHAR:
case SYBCHAR:
case SYBVARCHAR:
case SYBTEXT:
tdsdump_log(TDS_DBG_FUNC, "%L cs_convert() desttype =
character\n");
if (src_len > destlen) {
+ tdsdump_log(TDS_DBG_FUNC, "%L src_len >
destlen\n");
ret = CS_FAIL;
} else {
switch (destfmt->format) {
@@ -416,6 +418,7 @@
ret = CS_SUCCEED;
break;
default:
+ tdsdump_log(TDS_DBG_FUNC, "%L no
destination format specified!\n");
ret = CS_FAIL;
break;
}
Index: src/ctlib/ct.c
===================================================================
RCS file: /cvsroot/freetds/freetds/src/ctlib/ct.c,v
retrieving revision 1.107
diff -u -r1.107 ct.c
--- src/ctlib/ct.c 16 Nov 2003 08:19:58 -0000 1.107
+++ src/ctlib/ct.c 21 Nov 2003 10:33:23 -0000
@@ -49,7 +49,7 @@
*/
static int _ct_fetch_cursor(CS_COMMAND * cmd, CS_INT type, CS_INT offset,
CS_INT option, CS_INT * rows_read);
static int _ct_bind_data(CS_COMMAND * cmd, CS_INT offset);
-static int _ct_get_client_type(int datatype, int size);
+static int _ct_get_client_type(int datatype, int usertype, int size);
static int _ct_fetchable_results(CS_COMMAND * cmd);
static int _ct_process_return_status(TDSSOCKET * tds);

@@ -1369,6 +1369,11 @@
for (i = 0; i < resinfo->num_cols; i++) {
curcol = resinfo->columns[i];

+ tdsdump_log(TDS_DBG_FUNC, "%L _ct_bind_data(): column_type:
%d column_len: %d\n",
+ curcol->column_type,
+ curcol->column_cur_size
+ );
+
if (curcol->column_hidden)
continue;

@@ -1397,7 +1402,7 @@

if (dest && !tds_get_null(resinfo->current_row, i)) {

- srctype = _ct_get_client_type(curcol->column_type,
curcol->column_size);
+ srctype = _ct_get_client_type(curcol->column_type,
curcol->column_usertype, curcol->column_size);

src = &(resinfo->current_row[curcol->column_offset]);
if (is_blob_type(curcol->column_type))
@@ -1413,7 +1418,8 @@
destfmt.locale = cmd->con->locale;
destfmt.format = curcol->column_bindfmt;
/* if convert return FAIL mark error but process
other columns */
- if (cs_convert(ctx, &srcfmt, (CS_VOID *) src,
&destfmt, (CS_VOID *) dest, &len) != CS_SUCCEED) {
+ if ((result= cs_convert(ctx, &srcfmt, (CS_VOID *)
src, &destfmt, (CS_VOID *) dest, &len) != CS_SUCCEED)) {
+ tdsdump_log(TDS_DBG_FUNC, "%L
cs_convert-result = %d\n", result);
result = 1;
len = 0;
tdsdump_log(TDS_DBG_INFO1, "%L \n convert
failed for %d \n", srcfmt.datatype);
@@ -1472,9 +1478,9 @@


static int
-_ct_get_client_type(int datatype, int size)
+_ct_get_client_type(int datatype, int usertype, int size)
{
- tdsdump_log(TDS_DBG_FUNC, "%L _ct_get_client_type(type %d, size
%d)\n", datatype, size);
+ tdsdump_log(TDS_DBG_FUNC, "%L _ct_get_client_type(type %d, user %d,
size %d)\n", datatype, usertype, size);
switch (datatype) {
case SYBBIT:
case SYBBITN:
@@ -1568,6 +1574,11 @@
case SYBUNIQUE:
return CS_UNIQUE_TYPE;
break;
+ case SYBLONGBINARY:
+ if (usertype == 35)
+ return CS_UNIVARCHAR_TYPE;
+ return CS_BINARY_TYPE;
+ break;
}

return CS_FAIL;
@@ -1635,6 +1646,8 @@
case CS_LONGBINARY_TYPE: /* vicm */
return SYBLONGBINARY;
break;
+ case CS_UNIVARCHAR_TYPE:
+ return SYBUNIVARCHAR;
default:
return -1;
break;
@@ -1703,7 +1716,7 @@
strncpy(datafmt->name, curcol->column_name, len);
datafmt->namelen = len;
/* need to turn the SYBxxx into a CS_xxx_TYPE */
- datafmt->datatype = _ct_get_client_type(curcol->column_type,
curcol->column_size);
+ datafmt->datatype = _ct_get_client_type(curcol->column_type,
curcol->column_usertype, curcol->column_size);
tdsdump_log(TDS_DBG_INFO1, "%L ct_describe() datafmt->datatype = %d
server type %d\n", datafmt->datatype,
curcol->column_type);
/* FIXME is ok this value for numeric/decimal? */
Index: src/tds/convert.c
===================================================================
RCS file: /cvsroot/freetds/freetds/src/tds/convert.c,v
retrieving revision 1.125
diff -u -r1.125 convert.c
--- src/tds/convert.c 24 Oct 2003 10:11:11 -0000 1.125
+++ src/tds/convert.c 21 Nov 2003 10:33:23 -0000
@@ -1608,6 +1608,7 @@
assert(srclen >= 0 && srclen <= 2147483647u);

switch (srctype) {
+ case SYBUNIVARCHAR:
case CASE_ALL_CHAR:
length = tds_convert_char(srctype, src, srclen, desttype, cr);
break;
@@ -3220,6 +3221,9 @@
break;
case SYBLONGBINARY:
result = "SYBLONGBINARY";
+ break;
+ case SYBUNIVARCHAR:
+ result = "SYBUNIVARCHAR";
break;
default:
break;
Index: src/tds/token.c
===================================================================
RCS file: /cvsroot/freetds/freetds/src/tds/token.c,v
retrieving revision 1.226
diff -u -r1.226 token.c
--- src/tds/token.c 16 Nov 2003 18:10:18 -0000 1.226
+++ src/tds/token.c 21 Nov 2003 10:33:23 -0000
@@ -1520,8 +1520,11 @@
switch (curcol->column_varint_size) {
case 4:
curcol->column_size = tds_get_int(tds);
- curcol->table_namelen =
- tds_get_string(tds, tds_get_smallint(tds),
curcol->table_name, sizeof(curcol->table_name) - 1);
+ /* Only read table_name for blob columns (eg. not for
SYBLONGBINARY) */
+ if (is_blob_type (curcol->column_type)) {
+ curcol->table_namelen =
+ tds_get_string(tds, tds_get_smallint(tds),
curcol->table_name, sizeof(curcol->table_name) - 1);
+ }
break;
case 2:
curcol->column_size = tds_get_smallint(tds);
@@ -1812,7 +1815,7 @@
{
unsigned char *dest;
int len, colsize;
- int fillchar;
+ int fillchar, pos;
TDSBLOBINFO *blob_info = NULL;

tdsdump_log(TDS_DBG_INFO1, "%L processing row. column is %d varint
size = %d\n", i, curcol->column_varint_size);
@@ -1830,6 +1833,15 @@
tds_set_null(current_row, i);
return TDS_SUCCEED;
}
+
+ /* LONGBINARY
+ * This type just stores a 4-byte length
+ */
+ if (curcol->column_type == SYBLONGBINARY) {
+ colsize = tds_get_int(tds);
+ break;
+ }
+
/* It's a BLOB... */
len = tds_get_byte(tds);
blob_info = (TDSBLOBINFO *) &
(current_row[curcol->column_offset]);
@@ -1949,6 +1961,7 @@
} else { /* non-numeric and non-blob */
if (is_char_type(curcol->column_type)) {
/* this shouldn't fail here */
+ tdsdump_log(TDS_DBG_INFO1, "%L curcol->iconv_info?
%d\n", (int)curcol->iconv_info);
if (tds_get_char_data(tds, (char *) dest, colsize,
curcol) == TDS_FAIL)
return TDS_FAIL;
} else {
@@ -1968,6 +1981,11 @@
break;
/* FIXME use client charset */
fillchar = ' ';
+ /* just to prevent \0 to interrupt display, as long as we
cannot decode utf-16 */
+ case SYBLONGBINARY:
+ for (pos= 0; pos < colsize; pos++) {
+ if (dest[pos] == '\0') { dest[pos]= '.'; }
+ }
case SYBBINARY:
case XSYBBINARY:
if (colsize < curcol->column_size)
@@ -3151,6 +3169,7 @@
TYPE(SYBAOPSUM, "sum");

TYPE(SYBBINARY, "binary");
+ TYPE(SYBLONGBINARY, "longbinary");
TYPE(SYBBIT, "bit");
TYPE(SYBBITN, "bit-null");
TYPE(SYBCHAR, "char");



Archive powered by MHonArc 2.6.24.

Top of Page