Skip to Content.
Sympa Menu

freetds - Re: PHP's mssql_fetch_row inserting '\0' on strings ?

freetds AT lists.ibiblio.org

Subject: FreeTDS Development Group

List archive

Chronological Thread  
  • From: "Brian Bruns" <camber AT ais.org>
  • To: freetds AT franklin.oit.unc.edu
  • Subject: Re: PHP's mssql_fetch_row inserting '\0' on strings ?
  • Date: Thu, 20 Jun 2002 16:19:23 -0400


> Hi Brian, thks for joining this discussion.
>

>
> BTW: any advantage of using one instead of the other?
>

Sybase ctlib is the newer of the two api's. Sybase wanted a next
generation API that would handle a whole range of functions beyond simple
client/database interface that was dblib. For PHP's purposes, it doesn't
matter much really.

> > I'm going to take a wild guess that the size of the
> > resultant data (with all those nulls) is twice the size of the data?
>
> Bingo! Nice shot =) Yes, resultant data with embedded \0s is twice the
> size of the "right" data. So, this proves the assumptions that UCS-2 vs.
> ASCII is the source of the confusion, doesn't it? Maybe PHP is allocating
> a buffer for UCS-2 data and is indeed receiving ASCII?

Thanks, looks like a duck, quacks like a duck as they say.

> Looks like we're narrowing the probl down =)
>
> > If so, dbdatlen() or it's ctlib counterpart (length bind) is a possible
> > culprit in FreeTDS, but we need a bit more info.
>
> Great. Just let me know how I can help any further, I will be glad to do
> it.

Ok, in src/tds/token.c we have:

curcol->cur_row_size = colsize;

in which the size of the column (in bytes) is copied off to be used later
by dbdatlen() (as suspected):

ret = colinfo->cur_row_size;

Now, the problem is one of unicode, encodings, iconv, and a bunch of other
stuff, which I'll try to explain with as much clarity as I can muster.
But first, props to Mark who fixed the dbdatlen() implementation that is
there now, he could not have forseen this problem!

Character data on the wire under TDS 7.0 is transmitted in UCS-2 encoding
(fixed length 2 bytes per character). In order for most unix-like
programs to deal with it, we need to turn it into something useful, that
something is usually ascii or latin1. In doing so we generally are
shrinking the number of bytes in the string (halving in the most common
case).

Actually, reviewing the code just now I'm realizing that cur_row_size is
wrong in the case of unicode strings, because the data has already been
converted and it's probably a two-liner fix. Try replacing

curcol->cur_row_size = colsize;

in src/tds/token.c(tds_process_row) with

if (curcol->column_unicodedata) {
curcol->cur_row_size = strlen(dest);
} else {
curcol->cur_row_size = colsize;
}

This will work for all null terminated iconv character sets, so setting
'client charset' to UCS-2 or UCS-4 will produce odd behaviour, not that it
probably worked before anyway...but for disclosures sake, it really won't
now.

> Thks for the help.
>
> Best,
>
> Andre




Archive powered by MHonArc 2.6.24.

Top of Page