Re: [PATCH] Problem with VARCHAR in sybase.
Eddy Pronk <[email protected]>
| Newsgroups | gmane.comp.db.tds.freetds |
|---|---|
| Message-ID | <[email protected]> |
> Eddy Pronk wrote: >> My database had a table with a column which was VARCHAR(20) >> One of the rows had exactly 20 characters. >> With a simple SELECT it hit this piece of code which returns CS_FAIL >> without logging anything: >> >> 538 case CS_FMT_NULLTERM: > ... >> I included a patch below. > ... >> If I allocate 1 byte extra for the null terminator my query works. > > Thank you for the patch. You've highlighted a problem, but I don't think > your fix is the right one. > > In the first place, ct-lib needs some time and attention paid to error > messages. There are many places where it works if used correctly but > fails silently (except for the return code) if not. We need a function > similar to dbperror(). > > Second, afaict CS_FMT_NULLTERM is invalid in cs_convert (cf. > http://manuals.sybase.com:80/onlinebooks/group-oc/ocg1250e/occpr/@ebt-link;pt=2420?target=%25N%14_2686_START_RESTART_N%25). > > > Third, even if valid, istm the code is basically right: if the destination > buffer does not have room for a NULL terminator and the format > specification for the conversion demands one, the conversion should fail. > > I'll look at the code again tonight. The context in which I found this problem was by using libdbi which has a driver to talk to freetds. I fixed it this way because I think destlen is setup by freetds. Maybe the way libdbi uses the API needs attention. Eddy ---------------------------- Original Message ---------------------------- Subject: [PATCH] Problem with VARCHAR in freetds (sybase) From: "Eddy Pronk" <[email protected]> Date: Sun, June 29, 2008 10:25 am To: [email protected] -------------------------------------------------------------------------- I used libdbi with the freetds driver from Linux to connect to a sybase server on Solaris. My database had a table with a column which was VARCHAR(20) One of the rows had exactly 20 characters. In this case libdbi returns an empty result. I found 2 problems: * dbd_freetds.c doesn't allocate enought to store the a null terminator. * freetds ignores a field when it has exactly 20 characters. I think I fixed both. I used valgrind to find the memory allocation usage. diff --git a/drivers/freetds/dbd_freetds.c b/drivers/freetds/dbd_freetds.c index e7df09a..5b5e13e 100644 --- a/drivers/freetds/dbd_freetds.c +++ b/drivers/freetds/dbd_freetds.c @@ -977,8 +977,9 @@ dbi_row_t *_dbd_freetds_buffers_binding(dbi_conn_t * conn, dbi_result_t * result /* * Result is more that 8 bytes - * allocate additional memory + * 1 extra byte for \0 */ - addr = row->field_values[idx].d_string = (char *) malloc(row->field_sizes[idx]); + addr = row->field_values[idx].d_string = (char *) malloc(row->field_sizes[idx] + 1); break; default: /* Prepare union to data copy */ --