PEPPLER.ORG
Michael Peppler
Sybase Consulting
Menu
Home
Sybase on Linux
Install Guide for Sybase on Linux
General Sybase Resources
General Perl Resources
Freeware
Sybperl
Sybase::Simple
DBD::Sybase
BCP Tool
Bug Tracker
Mailing List Archive
Downloads Directory
FAQs
Sybase on Linux FAQ
Sybperl FAQ
Personal
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 12.0.0.3 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
database.

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) {
        complain(
            "Cannot read text/image data from $path.",
            "The file is empty."
        );
        close(IMAGE);
        return 0;
    }

    # In preparation for saving the image data, set the image column to
NULL.
    #
    $query = qq(
        update $table
        set $image_col = NULL
        where $id_col = $id
    );
    $dbh->ct_sql($query);

    # Make sure a row exists to take the blob.
    #
    if ($dbh->{ROW_COUNT} < 1) {
        complain(
            "Cannot write text/image data read from $path.",
            "Apparently no row exists in table $table where $id_col = $id."
        );
        close(IMAGE);
        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";
    $dbh->ct_execute($query);
    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.
    #
    $dbh->ct_send;
    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.
    #
    complain(
        "Detected a size mismatch while writing text/image data read from
$path.",
        "The file size is $size bytes, but $total_read bytes were written
to the database."
    ) if $total_read != $size;

    close(IMAGE);
    $total_read;
}

file2db($dbh, 'mytable', 'name', '"foo"',  'filedata',
"/james/jpegs/foo.jpg");

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