Question

I am trying to copy some blob data from one sqlite table to another in C++. However, once the data has been copied over to the new table, it seems to be getting corrupted. The said data contains some jpeg images. The code I am using to copy from TABLE1 to TABLE2 is shown below:

// Read the blob from the database
    int64_t rowID = 0;
    sscanf( id.c_str(), "%llu", &rowID );

    sqlite3_blob* blobHandle = NULL;
    if( sqlite3_blob_open( m_dbHandle_temp, "main", m_currentTileTable.c_str(), "tile_data", rowID, 0, &blobHandle ) != SQLITE_OK )
    {
        sqlite3_blob_close( blobHandle ); // An SQLite blob will be initialised regardless of the success of 'sqlite3_blob_open'
        return false;
    }


    tiles_insert_statement.append( ")" );

    // Copy blob to database
    sqlite3_stmt *stmt = 0;
    const char* tail;
    sqlite3_prepare_v2( m_dbHandle, tiles_insert_statement.c_str(), strlen( tiles_insert_statement.c_str() )+1, &stmt, &tail );
    int bindSuccess = sqlite3_bind_blob( stmt, 1, blobHandle, sqlite3_blob_bytes( blobHandle ), SQLITE_TRANSIENT );
    if( sqlite3_step( stmt ) != SQLITE_DONE ) 
        printf( "Error message: %s\n", sqlite3_errmsg( m_dbHandle ) );
    sqlite3_finalize( stmt );

    // close handles
    sqlite3_blob_close( blobHandle );

Is there anything I am doing wrong in the above code, the reason I say that it is getting corrupted is because, I am reading the blobs on an android device to be displayed in an image viewer. The blobs in the TABLE 1 can be read and displayed fine, however the ones in TABLE 2 do not display anything. Any help is greatly appreaciated.

SOLUTION:

// Read the blob from the database
    int64_t rowID = 0;
    sscanf( id.c_str(), "%llu", &rowID );

    sqlite3_blob* blobHandle = NULL;
    if( sqlite3_blob_open( m_dbHandle_temp, "main", m_currentTileTable.c_str(), "tile_data", rowID, 0, &blobHandle ) != SQLITE_OK )
    {
        sqlite3_blob_close( blobHandle ); // An SQLite blob will be initialised regardless of the success of 'sqlite3_blob_open'
        return false;
    }

    unsigned int length = sqlite3_blob_bytes( blobHandle );

    // TODO - instances of this class OWN the buffer.
    // Delete the buffer in the destructor ;)
    unsigned char* buffer = new unsigned char[ length ];
    if( sqlite3_blob_read( blobHandle, buffer, length, 0 ) != SQLITE_OK )
    {
        return false;
    }

    tiles_insert_statement.append( ")" );

    sqlite3_stmt *stmt = 0;
    const char* tail;
    sqlite3_prepare_v2( m_dbHandle, tiles_insert_statement.c_str(), strlen( tiles_insert_statement.c_str() )+1, &stmt, &tail );
    int bindSuccess = sqlite3_bind_blob( stmt, 1, buffer, length, SQLITE_TRANSIENT );
    if( sqlite3_step( stmt ) != SQLITE_DONE ) 
        printf( "Error message: %s\n", sqlite3_errmsg( m_dbHandle ) );
    sqlite3_finalize( stmt );

    // close handles
    sqlite3_blob_close( blobHandle );
Was it helpful?

Solution

sqlite3_bind_blob expects a pointer to the actual blob data; it is not possible to use a blob handle for that.

To get the blob data as a memory chunk, execute a query like SELECT tile_data FROM MyTable WHERE ... and read the value with sqlite3_column_blob.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top