Blobl_write problem

Hi,

blob_open, read, bytes and close work very well, but when I try to write, always catch “Failure 1 (SQL logic error)”

I try to write a byte, two thre but never work.

the blob column it’s a text with 12 characters

there are any problem with blob_write and sqlcipher?

Hello @Manuel_Peliz - there aren’t any known issues with SQLCipher and the incremental BLOB API.

The most likely reason you would receiving a SQL logic error is that you are attempting to write past the end of the BLOB. SQLite and SQLCipher will not increase the size of a BLOB using sqlite3_blob_write. You can only modify existing BLOB contents with that function. In practice this means you need to preallocate a BLOB, e.g. using sqlite3_bind_zeroblob(), of a sufficient size. You can refer to the documentation for more details.

If this is not the problem, and you are sure you are writing to an appropriately sized pre-allocated BLOB, please provide us with a short code sample to reproduce the problem and we’ll take a closer look.

Hello sjlombardo thanks for your answer.

I’m nearly sure. I’m using bindzeroblob or bind_blob too, but always fail

this is my code:

-------------------------------------------------------------- open java:

    SQLiteDatabase.loadLibs(this);
    File databaseFile = getDatabasePath("demo.db");
    databaseFile.mkdirs();
    databaseFile.delete();
    SQLiteDatabase database = SQLiteDatabase.openOrCreateDatabase(databaseFile, "test123", null);
    String text= "";
    for(int cont=0;cont<1024;cont++){
        text+="1";
    }
    byte[] bytes = text.getBytes();
    database.execSQL("DROP TABLE IF EXISTS files");
    database.execSQL("CREATE TABLE IF NOT EXISTS files (\n" +
            "    path VARCHAR (128) COLLATE NOCASE,\n" +
            "    name VARCHAR (32)  COLLATE NOCASE,\n" +
            "    file BLOB\n" +
            ");\n");
    SQLiteStatement stm = database.compileStatement("INSERT INTO files (path,name,file) VALUES (?,?,?)");
    stm.bindString(1,"/path/to/file/");
    stm.bindString(2,"filename.txt");
    stm.bindBlob(3,bytes);
    //stm.bindZeroBlob(3,bytes.length);
    long result = stm.executeInsert();

    Log.i("TAG","result: " + Long.toString(result));

    stm = database.compileStatement("SELECT rowid FROM files limit 1");

    long rowid = stm.simpleQueryForLong();

    Log.i("TAG","rowid: " + Long.toString(rowid));

    long hblob = database.blob_open("main","files", "file", rowid, 1);

    Log.i("TAG","hblob: " + Long.toString(hblob));

    if( hblob != 0  ) {

        int size = database.blob_bytes(hblob);

        Log.i("TAG","size: " + Integer.toString(size));

        bytes[0] = 'a';
        bytes[1] = 'a';
        bytes[2] = 'a';
        bytes[3] = 'a';
        bytes[4] = 'a';

        //int wres = database.blob_write(hblob, bytes, 5);

        int wres = database.blob_write(hblob, bytes, bytes.length);

        Log.i("TAG","blob_write result: " + Integer.toString(wres));

        byte[] buffer = database.blob_read(hblob, size,0);

        String str = new String(buffer);

        Log.i("TAG","resultado: " + str);

        database.blob_close(hblob);

    }

-------------------------------------------------------------- close java:

write fail, read return 11111111… but no aaaaa111111…

-------------------------------------------------------------- ndk:

static jlong native_blob_open(JNIEnv *env, jobject object, jstring _zDb, jstring _zTable, jstring _zColumn, jlong _iRow, jint _mode) {
sqlite3 * handle = (sqlite3 *)env->GetLongField(object, offset_db_handle);
LOGI(“native_blob_open\n”);
sqlite3_blob * ppBlob = {0};
if (handle != NULL) {
char const *zDb = env->GetStringUTFChars(_zDb,NULL);
char const *zTable = env->GetStringUTFChars(_zTable,NULL);
char const *zColumn = env->GetStringUTFChars(_zColumn,NULL);
int err = sqlite3_blob_open( handle, zDb, zTable, zColumn, _iRow, _mode, & ppBlob );
if (err != SQLITE_OK) {
LOGE(“Failure %d (%s)\n”, err, sqlite3_errmsg(handle));
}
env->ReleaseStringUTFChars(_zDb, zDb);
env->ReleaseStringUTFChars(_zTable, zTable);
env->ReleaseStringUTFChars(_zColumn, zColumn);
return (intptr_t)ppBlob;
}
return 0L;
}

static jint native_blob_bytes(JNIEnv *env, jobject object, jlong _sqlblob) {
sqlite3 * handle = (sqlite3 *)env->GetLongField(object, offset_db_handle);
LOGI(“native_blob_bytes\n”);
sqlite3_blob *ppBlob = {0};
ppBlob = (sqlite3_blob *)_sqlblob;
return sqlite3_blob_bytes(ppBlob);
}

static jbyteArray native_blob_read(JNIEnv *env, jobject object, jlong _sqlblob, jint _size, jint _offset) {
sqlite3 * handle = (sqlite3 *)env->GetLongField(object, offset_db_handle);
LOGI(“native_blob_read\n”);
sqlite3_blob * ppBlob = {0};
ppBlob = (sqlite3_blob )_sqlblob;
jbyteArray byteArray = env->NewByteArray(_size);
if( byteArray == NULL ) {
LOGE(“native_blob_read out of memory\n”);
return NULL;
}
jbyte * buffer = env->GetByteArrayElements( byteArray, NULL );
if( buffer == NULL ) {
LOGE(“native_blob_read out of memory\n”);
return NULL;
}
sqlite3_blob_read( ppBlob, (void
)buffer, _size, _offset );
env->SetByteArrayRegion( byteArray, 0, _size, buffer );
return byteArray;
}

static int native_blob_write(JNIEnv *env, jobject object, jlong _sqlblob, jbyteArray _bytearray, jint _offset) {
sqlite3 * handle = (sqlite3 *)env->GetLongField(object, offset_db_handle);
LOGI(“native_blob_write\n”);
sqlite3_blob *ppBlob = {0};
ppBlob = (sqlite3_blob )_sqlblob;
jint len = env->GetArrayLength( _bytearray );
jbyte * buffer = env->GetByteArrayElements( _bytearray, NULL );
int result = sqlite3_blob_write( ppBlob, (void
)buffer, len, _offset );
env->ReleaseByteArrayElements( _bytearray, buffer, JNI_ABORT );
if (result != SQLITE_OK) {
LOGE(“Failure %d (%s)\n”, result, sqlite3_errmsg(handle));
}
return result;
}

static jlong native_blob_close(JNIEnv *env, jobject object, jlong _sqlblob) {
sqlite3 * handle = (sqlite3 *)env->GetLongField(object, offset_db_handle);
LOGI(“native_blob_close\n”);
sqlite3_blob *ppBlob = {0};
ppBlob = (sqlite3_blob *)_sqlblob;
sqlite3_blob_close(ppBlob);
return 0L;
}

Hello @Manuel_Peliz - the 4th final parameter to sqlite3_blob_write is the offset in the BLOB. You are passing that the length of the byte buffer.

That is resulting in an attempt to write at the end of the BLOB. Why don’t you try the following instead:

int wres = database.blob_write(hblob, bytes, 0);

uuuuupps You are right ¡¡¡ I’m stupid, sorry, 2 days searching the problem.