send_retrieve_part_blob.cpp

This example shows how to insert a blob in chunks and retrieve it in chunks too.

// *********************************************************************
// Copyright 1994-2008 iAnywhere Solutions, Inc.  All rights reserved.
// This sample code is provided AS IS, without warranty or liability
// of any kind.
//
// You may use, reproduce, modify and distribute this sample code
// without limitation, on the condition that you retain the foregoing
// copyright notice and disclaimer as to the original iAnywhere code.
//
// *********************************************************************
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "sacapidll.h"

int main( )
{
    SQLAnywhereInterface api;
    a_sqlany_connection *conn;
    a_sqlany_stmt       *stmt;
    unsigned int         I;
    unsigned char       *data;
    unsigned int         size = 1024*1024; // 1MB blob
    int                  code;
    a_sqlany_data_value  value;
    int                  num_cols;
    unsigned char        retrieve_buffer[4096];
    a_sqlany_data_info   dinfo;
    int                  bytes_read;
    size_t               total_bytes_read;
    unsigned int         max_api_ver;

    if( !sqlany_initialize_interface( &api, NULL ) ) {
        printf( "Could not initialize the interface!\n" );
        exit( 0 );
    }

    assert( api.sqlany_init( "my_php_app", SQLANY_CURRENT_API_VERSION, &max_api_ver ) );
    conn = api.sqlany_new_connection();

    if( !api.sqlany_connect( conn, "uid=dba;pwd=sql" ) ) {
        char buffer[SACAPI_ERROR_SIZE];
        code = api.sqlany_error( conn, buffer, sizeof(buffer) );
        printf( "Could not connection[%d]:%s\n", code, buffer );
        goto clean;
    }

    printf( "Connected successfully!\n" );

    api.sqlany_execute_immediate( conn, "drop table my_blob_table" );
    assert( api.sqlany_execute_immediate( conn, "create table my_blob_table (size integer, data long binary)" ) != 0);

    // 1. Starting to insert blob operation
    stmt = api.sqlany_prepare( conn, "insert into my_blob_table( size, data) values( ?, ? )" );
    assert( stmt != NULL );


    // 1.1 We must first bind the parameters
    a_sqlany_bind_param param;

    api.sqlany_describe_bind_param( stmt, 0, &param );
    param.value.buffer = (char *)&size;
    param.value.type   = A_VAL32;
    param.value.is_null= NULL;
    param.direction    = DD_INPUT;
    api.sqlany_bind_param( stmt, 0, &param );

    api.sqlany_describe_bind_param( stmt, 1, &param );
    param.value.buffer = NULL;
    param.value.type   = A_BINARY;
    param.value.is_null= NULL;
    param.direction    = DD_INPUT;
    api.sqlany_bind_param( stmt, 1, &param );

    data = (unsigned char *)malloc( size );
    for( I = 0; I < size; I++ ) {
        data[i] = I % 256;
    }

    // 1.2 upload the blob data to the server in chunks
    for( I = 0; I < size; I += 4096 ) {
        if( !api.sqlany_send_param_data( stmt, 1, (char *)&data[i], 4096 )) {
            char buffer[SACAPI_ERROR_SIZE];
            code = api.sqlany_error( conn, buffer, sizeof(buffer) );
            printf( "Could not send param[%d]:%s\n", code, buffer );
        }
    }

    // 1.3 actually do the row insert operation
    assert( api.sqlany_execute( stmt ) == 1 );

    api.sqlany_commit( conn );

    api.sqlany_free_stmt( stmt );


    // 2. Now let's retrieve the blob
    stmt = api.sqlany_execute_direct( conn, "select * from my_blob_table" );
    assert( stmt != NULL );

    assert( api.sqlany_fetch_next( stmt ) == 1 );

    num_cols = api.sqlany_num_cols( stmt );

    assert( num_cols == 2 );

    api.sqlany_get_column( stmt, 0, &value );

    assert( I == size );
    assert( value.type == A_VAL32 );

    api.sqlany_get_data_info( stmt, 1, &dinfo );

    assert( dinfo.type == A_BINARY );
    assert( dinfo.data_size == size );
    assert( dinfo.is_null == 0 );

    // 2.1 Retrieve data in 4096 byte chunks
    total_bytes_read = 0;
    while( 1 ) {
        bytes_read = api.sqlany_get_data( stmt, 1, total_bytes_read, retrieve_buffer, sizeof(retrieve_buffer) );
        if( bytes_read <= 0 ) {
            break;
        }
        // verify the buffer contents
        for( I = 0; I < (unsigned int)bytes_read; I++ ) {
            assert( retrieve_buffer[i] == data[total_bytes_read+I] );
        }
        total_bytes_read += bytes_read;
    }
    assert( total_bytes_read == size );

    free(data );

    assert( api.sqlany_fetch_next( stmt ) == 0 );

    api.sqlany_free_stmt( stmt );

    api.sqlany_disconnect( conn );

clean:
    api.sqlany_free_connection( conn );

    api.sqlany_fini();

    sqlany_finalize_interface( &api );

    printf( "Success!\n" );
}