Michael Peppler
Sybase Consulting
Sybase on Linux
Install Guide for Sybase on Linux
General Sybase Resources
General Perl Resources
BCP Tool
Bug Tracker
Mailing List Archive
Downloads Directory
Sybase on Linux FAQ
Sybperl FAQ
Michael Peppler's resume

sybperl-l Archive

Up    Prev    Next    

From: jmcallister at dtint dot com
Subject: help with ct_send_data and image data
Date: Aug 16 2001 6:21PM

I'm getting the following OpenClient errors with Sybperl 2.13, Solaris 8
and ASE that I haven't seen before.

OPEN CLIENT MESSAGE: "ct_send_data(): user api layer: external error:
1481944 bytes exceeds the amount of bytes specified for this send data
operation.  Only 0 more bytes can be sent."
OPEN CLIENT MESSAGE: "ct_send(): protocol specific layer: internal Client
Library error: There is a tds state machine error. An illegal tds token
sequence was received."
OPEN CLIENT MESSAGE: "ct_results(): user api layer: external error: The
connection has been marked dead."
WARNING: Detected a size mismatch while writing text/image data read from
/james/jpegs/foo.jpg.    <-- These errors come from my code.
WARNING: The file size is 1481944 bytes, but 0 bytes were written to the

Here's the relevant code:

sub file2db {

    my($dbh, $table, $id_col, $id, $image_col, $path) = @_;
    my($size, $bytes_read, $total_read, $buffer) = (0, 0, 0, '');
    my($ret, $query, $restype, @row);

    # Open the file that holds the image data.
    if (! open(IMAGE, $path)) {
        complain("Unable to open file $path from which to read text/image
data ($!).");
        return 0;

    # Find out how big (in bytes) the file is.
    $size = -s IMAGE;
    if ($size <= 0) {
            "Cannot read text/image data from $path.",
            "The file is empty."
        return 0;

    # In preparation for saving the image data, set the image column to
    $query = qq(
        update $table
        set $image_col = NULL
        where $id_col = $id

    # Make sure a row exists to take the blob.
    if ($dbh->{ROW_COUNT} < 1) {
            "Cannot write text/image data read from $path.",
            "Apparently no row exists in table $table where $id_col = $id."
        return 0;

    # Select the image column for the new row. This primes the pump
    # for successive WRITETEXT calls.
    $query = "select $image_col from $table where $id_col = $id";
    while ($dbh->ct_results($restype) == CS_SUCCEED) {
        next unless $dbh->ct_fetchable($restype);
        while (@row = $dbh->ct_fetch) {
            $dbh->ct_data_info(CS_GET, 1);

    $dbh->ct_command(CS_SEND_DATA_CMD, '', CS_UNUSED, CS_COLUMN_DATA);
    $dbh->ct_data_info(CS_SET, 1, {total_txtlen => $size});

    # Read chunks of data from disk and send them to the SQL server.
    # Keep track of the total number of bytes read.
    while (($bytes_read = sysread(IMAGE, $buffer, $::gParams{in_buf_sz})) >
0) { ### <=== I've tried different values of buffer size including numbers
larger than the file size.

        $ret = $dbh->ct_send_data($buffer, $bytes_read);
        last if $ret == CS_FAIL;
        $total_read += $bytes_read;

    # Finish the TEXT/IMAGE update.
    while ($dbh->ct_results($restype) == CS_SUCCEED) {
        next unless $dbh->ct_fetchable($restype);
        while (@row = $dbh->ct_fetch) { ; }

    # Make sure the total bytes read and sent matches the total file size.
        "Detected a size mismatch while writing text/image data read from
        "The file size is $size bytes, but $total_read bytes were written
to the database."
    ) if $total_read != $size;


file2db($dbh, 'mytable', 'name', '"foo"',  'filedata',

This code worked well on earlier versions of perl, Sybperl, Solaris and
Sybase. Any clues, suggestions, etc. would be greatly appreciated.

Thanks in advance,

James McAllister