mirror of
https://github.com/sqlite/sqlite.git
synced 2025-07-30 19:03:16 +03:00
Add incremental blob I/O support to JNI wrapper1.
FossilOrigin-Name: 7f1c76fe930d69a0274f70fa7b7e68e0db6226b731a065fa57d0936c8400ffb0
This commit is contained in:
@ -1633,7 +1633,7 @@ public class Tester1 implements Runnable {
|
||||
sqlite3_finalize(stmt);
|
||||
|
||||
b = sqlite3_blob_open(db, "main", "t", "a",
|
||||
sqlite3_last_insert_rowid(db), 1);
|
||||
sqlite3_last_insert_rowid(db), 0);
|
||||
affirm( null!=b );
|
||||
rc = sqlite3_blob_reopen(b, 2);
|
||||
affirm( 0==rc );
|
||||
|
@ -17,6 +17,7 @@ import org.sqlite.jni.capi.CApi;
|
||||
import org.sqlite.jni.capi.sqlite3;
|
||||
import org.sqlite.jni.capi.sqlite3_stmt;
|
||||
import org.sqlite.jni.capi.sqlite3_backup;
|
||||
import org.sqlite.jni.capi.sqlite3_blob;
|
||||
import org.sqlite.jni.capi.OutputPointer;
|
||||
|
||||
/**
|
||||
@ -473,7 +474,7 @@ public final class Sqlite implements AutoCloseable {
|
||||
if( 0!=rc ){
|
||||
if( CApi.SQLITE_NOMEM==rc ){
|
||||
throw new OutOfMemoryError();
|
||||
}else if( null==db || 0==CApi.sqlite3_errcode(db)){
|
||||
}else if( null==db || 0==CApi.sqlite3_errcode(db) ){
|
||||
throw new SqliteException(rc);
|
||||
}else{
|
||||
throw new SqliteException(db);
|
||||
@ -1630,4 +1631,76 @@ public final class Sqlite implements AutoCloseable {
|
||||
checkRc( CApi.sqlite3_set_authorizer( thisDb(), ac ) );
|
||||
}
|
||||
|
||||
/**
|
||||
Object type for use with blobOpen()
|
||||
*/
|
||||
public final class Blob implements AutoCloseable {
|
||||
private Sqlite db;
|
||||
private sqlite3_blob b;
|
||||
Blob(Sqlite db, sqlite3_blob b){
|
||||
this.db = db;
|
||||
this.b = b;
|
||||
}
|
||||
|
||||
/**
|
||||
Analog to sqlite3_blob_close().
|
||||
*/
|
||||
@Override public void close(){
|
||||
if( null!=b ){
|
||||
CApi.sqlite3_blob_close(b);
|
||||
b = null;
|
||||
db = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Analog to sqlite3_blob_reopen() but throws on error.
|
||||
*/
|
||||
public void reopen(long newRowId){
|
||||
db.checkRc( CApi.sqlite3_blob_reopen(b, newRowId) );
|
||||
}
|
||||
|
||||
/**
|
||||
Analog to sqlite3_blob_write() but throws on error.
|
||||
*/
|
||||
public void write( byte[] bytes, int atOffset ){
|
||||
db.checkRc( CApi.sqlite3_blob_write(b, bytes, atOffset) );
|
||||
}
|
||||
|
||||
/**
|
||||
Analog to sqlite3_blob_read() but throws on error.
|
||||
*/
|
||||
public void read( byte[] dest, int atOffset ){
|
||||
db.checkRc( CApi.sqlite3_blob_read(b, dest, atOffset) );
|
||||
}
|
||||
|
||||
/**
|
||||
Analog to sqlite3_blob_bytes().
|
||||
*/
|
||||
public int bytes(){
|
||||
return CApi.sqlite3_blob_bytes(b);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Analog to sqlite3_blob_open(). Returns a Blob object for the
|
||||
given database, table, column, and rowid. The blob is opened for
|
||||
read-write mode if writeable is true, else it is read-only.
|
||||
|
||||
The returned object must eventually be freed, before this
|
||||
database is closed, by either arranging for it to be auto-closed
|
||||
or calling its close() method.
|
||||
|
||||
Throws on error.
|
||||
*/
|
||||
public Blob blobOpen(String dbName, String tableName, String columnName,
|
||||
long iRow, boolean writeable){
|
||||
final OutputPointer.sqlite3_blob out = new OutputPointer.sqlite3_blob();
|
||||
checkRc(
|
||||
CApi.sqlite3_blob_open(thisDb(), dbName, tableName, columnName,
|
||||
iRow, writeable ? 1 : 0, out)
|
||||
);
|
||||
return new Blob(this, out.take());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -912,6 +912,32 @@ public class Tester2 implements Runnable {
|
||||
db.close();
|
||||
}
|
||||
|
||||
private void testBlobOpen(){
|
||||
final Sqlite db = openDb();
|
||||
|
||||
execSql(db, "CREATE TABLE T(a BLOB);"
|
||||
+"INSERT INTO t(rowid,a) VALUES(1, 'def'),(2, 'XYZ');"
|
||||
);
|
||||
Sqlite.Blob b = db.blobOpen("main", "t", "a",
|
||||
db.lastInsertRowId(), true);
|
||||
affirm( 3==b.bytes() );
|
||||
b.write(new byte[] {100, 101, 102 /*"DEF"*/}, 0);
|
||||
b.close();
|
||||
Sqlite.Stmt stmt = db.prepare("SELECT length(a), a FROM t ORDER BY a");
|
||||
affirm( stmt.step() );
|
||||
affirm( 3 == stmt.columnInt(0) );
|
||||
affirm( "def".equals(stmt.columnText16(1)) );
|
||||
stmt.finalizeStmt();
|
||||
|
||||
b = db.blobOpen("main", "t", "a", db.lastInsertRowId(), false);
|
||||
b.reopen(2);
|
||||
final byte[] tgt = new byte[3];
|
||||
b.read( tgt, 0 );
|
||||
affirm( 100==tgt[0] && 101==tgt[1] && 102==tgt[2], "DEF" );
|
||||
b.close();
|
||||
db.close();
|
||||
}
|
||||
|
||||
private void runTests(boolean fromThread) throws Exception {
|
||||
List<java.lang.reflect.Method> mlist = testMethods;
|
||||
affirm( null!=mlist );
|
||||
|
Reference in New Issue
Block a user