FreeTDS / freetds

Official FreeTDS repository
http://www.freetds.org/
GNU General Public License v2.0
460 stars 157 forks source link

ct_data_info fails with Sybase ASE, DBD::Sybase test code #398

Open mpeppler opened 3 years ago

mpeppler commented 3 years ago

The Sybase docs mention that you should call ct_data_info() to retrieve the text pointer of a TEXT/IMAGE item after you have executed a SELECT for the item.

So for example:

create table blob_test(id int, data image) insert blob_test values(1, '')

Then execute a select on blob_test.data, fetch the row, and then call ct_data_info to fill the IODESC structure.

The corresponding code in DBD::Sybase (in perl) is:

my $sth = $dbh->prepare("select id, data from blob_test"); $sth->execute; while($sth->fetch) { $sth->syb_ct_data_info('CS_GET', 2) || print $sth->errstr, "\n"; }

This works fine with the Sybase libs - but fails with FreeTDS.

I think this is due to this test in ct.c's ct_data_info() function:

case CS_GET:

    if (colnum < 1 || colnum > resinfo->num_cols)
        return CS_FAIL;
    **if (colnum != cmd->get_data_item)**
        return CS_FAIL;

Looking at the code (latest from git) I only see one place with get_data_item is populated, and that's in ct_get_data - so using the above sequence colnum will never be equal to get_data_item.

Maybe this is set elsewhere, and I'm missing something?

Thanks!

freddy77 commented 3 years ago

Il giorno mer 21 apr 2021 alle ore 10:41 Michael Peppler @.***> ha scritto:

The Sybase docs mention that you should call ct_data_info() to retrieve the text pointer of a TEXT/IMAGE item after you have executed a SELECT for the item.

So for example:

create table blob_test(id int, data image) insert blob_test values(1, '')

Then execute a select on blob_test.data, fetch the row, and then call ct_data_info to fill the IODESC structure.

The corresponding code in DBD::Sybase (in perl) is:

my $sth = $dbh->prepare("select id, data from blob_test"); $sth->execute; while($sth->fetch) { $sth->syb_ct_data_info('CS_GET', 2) || print $sth->errstr, "\n"; }

This works fine with the Sybase libs - but fails with FreeTDS.

I think this is due to this test in ct.c's ct_data_info() function:

case CS_GET:

if (colnum < 1 || colnum > resinfo->num_cols) return CS_FAIL; if (colnum != cmd->get_data_item) return CS_FAIL;

Looking at the code (latest from git) I only see one place with get_data_item is populated, and that's in ct_get_data - so using the above sequence colnum will never be equal to get_data_item.

Maybe this is set elsewhere, and I'm missing something?

Thanks!

Hi Michael, I have no idea why that check is there. Especially given that the function accepts a column number and we have the information for that column. I'll try to look at the history if I find something. Did you try to remove that check?

Regards, Frediano

mpeppler commented 3 years ago

Hi Freddy I did try that - but it (obviously) fails with a segfault as cmd->iodesc is never populated, and the aim of ct_data_info() in this case is to retrieve the text pointer (iodesc->textptr)...

It's obviously not a critical component - but I suspect that cmd->iodesc should get populated on a select of a text/image column. I've not looked at the protocol data dump to try to see where that might be placed, or how that might work.