mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-07 02:42:48 +03:00
Wrap the sqlite3_backup API in the JNI wrapper1 API.
FossilOrigin-Name: 3ee6cc29d2111e7ad90860827c0ea808fdf07bc71defdade7e6794ec4a2a3ce2
This commit is contained in:
@@ -16,6 +16,7 @@ import java.nio.charset.StandardCharsets;
|
|||||||
import org.sqlite.jni.capi.CApi;
|
import org.sqlite.jni.capi.CApi;
|
||||||
import org.sqlite.jni.capi.sqlite3;
|
import org.sqlite.jni.capi.sqlite3;
|
||||||
import org.sqlite.jni.capi.sqlite3_stmt;
|
import org.sqlite.jni.capi.sqlite3_stmt;
|
||||||
|
import org.sqlite.jni.capi.sqlite3_backup;
|
||||||
import org.sqlite.jni.capi.OutputPointer;
|
import org.sqlite.jni.capi.OutputPointer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -767,14 +768,6 @@ public final class Sqlite implements AutoCloseable {
|
|||||||
"This \"cannot happen\": all possible result codes were checked already."
|
"This \"cannot happen\": all possible result codes were checked already."
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
Potential signature change TODO:
|
|
||||||
|
|
||||||
boolean step()
|
|
||||||
|
|
||||||
Returning true for SQLITE_ROW and false for anything else.
|
|
||||||
Those semantics have proven useful in the WASM/JS bindings.
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1019,4 +1012,114 @@ public final class Sqlite implements AutoCloseable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Encapsulates state related to the sqlite3 backup API. Use
|
||||||
|
Sqlite.initBackup() to create new instances.
|
||||||
|
*/
|
||||||
|
public static final class Backup implements AutoCloseable {
|
||||||
|
private sqlite3_backup b = null;
|
||||||
|
private Sqlite dbTo = null;
|
||||||
|
private Sqlite dbFrom = null;
|
||||||
|
|
||||||
|
|
||||||
|
public static final int DONE = CApi.SQLITE_DONE;
|
||||||
|
public static final int BUSY = CApi.SQLITE_BUSY;
|
||||||
|
public static final int LOCKED = CApi.SQLITE_LOCKED;
|
||||||
|
|
||||||
|
Backup(Sqlite dbDest, String schemaDest,Sqlite dbSrc, String schemaSrc){
|
||||||
|
this.dbTo = dbDest;
|
||||||
|
this.dbFrom = dbSrc;
|
||||||
|
b = CApi.sqlite3_backup_init(dbDest.nativeHandle(), schemaDest,
|
||||||
|
dbSrc.nativeHandle(), schemaSrc);
|
||||||
|
if(null==b) toss();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void toss(){
|
||||||
|
int rc = CApi.sqlite3_errcode(dbTo.nativeHandle());
|
||||||
|
if(0!=rc) throw new SqliteException(dbTo);
|
||||||
|
rc = CApi.sqlite3_errcode(dbFrom.nativeHandle());
|
||||||
|
if(0!=rc) throw new SqliteException(dbFrom);
|
||||||
|
throw new SqliteException(CApi.SQLITE_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
private sqlite3_backup getNative(){
|
||||||
|
if( null==b ) throw new IllegalStateException("This Backup is already closed.");
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
If this backup is still active, this completes the backup and
|
||||||
|
frees its native resources, otherwise it this is a no-op.
|
||||||
|
*/
|
||||||
|
public void finish(){
|
||||||
|
if( null!=b ){
|
||||||
|
CApi.sqlite3_backup_finish(b);
|
||||||
|
b = null;
|
||||||
|
dbTo = null;
|
||||||
|
dbFrom = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Equivalent to finish(). */
|
||||||
|
@Override public void close(){
|
||||||
|
this.finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Analog to sqlite3_backup_step(). Returns 0 if stepping succeeds
|
||||||
|
or, DONE if the end is reached, BUSY if one of the databases is
|
||||||
|
busy, LOCKED if one of the databases is locked, and throws for
|
||||||
|
any other result code or if this object has been closed. Note
|
||||||
|
that BUSY and LOCKED are not necessarily permanent errors, so
|
||||||
|
do not trigger an exception.
|
||||||
|
*/
|
||||||
|
public int step(int pageCount){
|
||||||
|
final int rc = CApi.sqlite3_backup_step(getNative(), pageCount);
|
||||||
|
switch(rc){
|
||||||
|
case 0:
|
||||||
|
case DONE:
|
||||||
|
case BUSY:
|
||||||
|
case LOCKED:
|
||||||
|
return rc;
|
||||||
|
default:
|
||||||
|
toss();
|
||||||
|
return CApi.SQLITE_ERROR/*not reached*/;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Analog to sqlite3_backup_pagecount().
|
||||||
|
*/
|
||||||
|
public int pageCount(){
|
||||||
|
return CApi.sqlite3_backup_pagecount(getNative());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Analog to sqlite3_backup_remaining().
|
||||||
|
*/
|
||||||
|
public int remaining(){
|
||||||
|
return CApi.sqlite3_backup_remaining(getNative());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Analog to sqlite3_backup_init(). If schemaSrc is null, "main" is
|
||||||
|
assumed. Throws if either this db or dbSrc (the source db) are
|
||||||
|
not opened, if either of schemaDest or schemaSrc are null, or if
|
||||||
|
the underlying call to sqlite3_backup_init() fails.
|
||||||
|
|
||||||
|
The returned object must eventually be cleaned up by either
|
||||||
|
arranging for it to be auto-closed (e.g. using
|
||||||
|
try-with-resources) or by calling its finish() method.
|
||||||
|
*/
|
||||||
|
public Backup initBackup(String schemaDest, Sqlite dbSrc, String schemaSrc){
|
||||||
|
thisDb();
|
||||||
|
dbSrc.thisDb();
|
||||||
|
if( null==schemaSrc || null==schemaDest ){
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Neither the source nor destination schema name may be null."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return new Backup(this, schemaDest, dbSrc, schemaSrc);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -603,6 +603,41 @@ public class Tester2 implements Runnable {
|
|||||||
affirm( 8 == val.value );
|
affirm( 8 == val.value );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void testBackup(){
|
||||||
|
final Sqlite dbDest = openDb();
|
||||||
|
|
||||||
|
try (Sqlite dbSrc = openDb()) {
|
||||||
|
execSql(dbSrc, new String[]{
|
||||||
|
"pragma page_size=512; VACUUM;",
|
||||||
|
"create table t(a);",
|
||||||
|
"insert into t(a) values(1),(2),(3);"
|
||||||
|
});
|
||||||
|
Exception e = null;
|
||||||
|
try {
|
||||||
|
dbSrc.initBackup("main",dbSrc,"main");
|
||||||
|
}catch(Exception x){
|
||||||
|
e = x;
|
||||||
|
}
|
||||||
|
affirm( e instanceof SqliteException );
|
||||||
|
e = null;
|
||||||
|
try (Sqlite.Backup b = dbDest.initBackup("main",dbSrc,"main")) {
|
||||||
|
affirm( null!=b );
|
||||||
|
int rc;
|
||||||
|
while( Sqlite.Backup.DONE!=(rc = b.step(1)) ){
|
||||||
|
affirm( 0==rc );
|
||||||
|
}
|
||||||
|
affirm( b.pageCount() > 0 );
|
||||||
|
b.finish();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try (Sqlite.Stmt q = dbDest.prepare("SELECT sum(a) from t")) {
|
||||||
|
q.step();
|
||||||
|
affirm( q.columnInt(0) == 6 );
|
||||||
|
}
|
||||||
|
dbDest.close();
|
||||||
|
}
|
||||||
|
|
||||||
private void runTests(boolean fromThread) throws Exception {
|
private void runTests(boolean fromThread) throws Exception {
|
||||||
List<java.lang.reflect.Method> mlist = testMethods;
|
List<java.lang.reflect.Method> mlist = testMethods;
|
||||||
affirm( null!=mlist );
|
affirm( null!=mlist );
|
||||||
|
14
manifest
14
manifest
@@ -1,5 +1,5 @@
|
|||||||
C Reimplement\sauto-extensions\sin\sJava\sfor\suse\swith\sthe\sJNI\swrapper1\sAPI.
|
C Wrap\sthe\ssqlite3_backup\sAPI\sin\sthe\sJNI\swrapper1\sAPI.
|
||||||
D 2023-11-04T21:51:34.589
|
D 2023-11-04T22:47:40.514
|
||||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||||
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
||||||
@@ -296,9 +296,9 @@ F ext/jni/src/org/sqlite/jni/test-script-interpreter.md f9f25126127045d051e918fe
|
|||||||
F ext/jni/src/org/sqlite/jni/wrapper1/AggregateFunction.java d5c108b02afd3c63c9e5e53f71f85273c1bfdc461ae526e0a0bb2b25e4df6483
|
F ext/jni/src/org/sqlite/jni/wrapper1/AggregateFunction.java d5c108b02afd3c63c9e5e53f71f85273c1bfdc461ae526e0a0bb2b25e4df6483
|
||||||
F ext/jni/src/org/sqlite/jni/wrapper1/ScalarFunction.java 43c43adfb7866098aadaaca1620028a6ec82d5193149970019b1cce9eb59fb03
|
F ext/jni/src/org/sqlite/jni/wrapper1/ScalarFunction.java 43c43adfb7866098aadaaca1620028a6ec82d5193149970019b1cce9eb59fb03
|
||||||
F ext/jni/src/org/sqlite/jni/wrapper1/SqlFunction.java 2833afdb9af5c1949bb35f4c926a5351fba9d1cdf0996864caa7b47827a346c7
|
F ext/jni/src/org/sqlite/jni/wrapper1/SqlFunction.java 2833afdb9af5c1949bb35f4c926a5351fba9d1cdf0996864caa7b47827a346c7
|
||||||
F ext/jni/src/org/sqlite/jni/wrapper1/Sqlite.java 3da22cb18d8544fff1c7184aeaa2516c20d63e8a31db848eb7470ce285b284dc
|
F ext/jni/src/org/sqlite/jni/wrapper1/Sqlite.java 8dd4cce0f0a42542af768a73c3c9e7bebd1c77207a35ba93de86c97d4c572847
|
||||||
F ext/jni/src/org/sqlite/jni/wrapper1/SqliteException.java 929a1e2ab4e135fbbae7f0d2d609f77cfbbc60bbec7ba789ce23d9c73bc6156e
|
F ext/jni/src/org/sqlite/jni/wrapper1/SqliteException.java 929a1e2ab4e135fbbae7f0d2d609f77cfbbc60bbec7ba789ce23d9c73bc6156e
|
||||||
F ext/jni/src/org/sqlite/jni/wrapper1/Tester2.java 03638a1774a95bcc7b5de440a5f1398720460e30fc480032a2e8be24e997d30c
|
F ext/jni/src/org/sqlite/jni/wrapper1/Tester2.java 3c2eda2efe45a051e371ba98abee34f51ceec3bb7d28dfde866646b650fcb426
|
||||||
F ext/jni/src/org/sqlite/jni/wrapper1/ValueHolder.java 7b89a7391f771692c5b83b0a5b86266abe8d59f1c77d7a0eccc9b79f259d79af
|
F ext/jni/src/org/sqlite/jni/wrapper1/ValueHolder.java 7b89a7391f771692c5b83b0a5b86266abe8d59f1c77d7a0eccc9b79f259d79af
|
||||||
F ext/jni/src/org/sqlite/jni/wrapper1/WindowFunction.java c7d1452f9ff26175b3c19bbf273116cc2846610af68e01756d755f037fe7319f
|
F ext/jni/src/org/sqlite/jni/wrapper1/WindowFunction.java c7d1452f9ff26175b3c19bbf273116cc2846610af68e01756d755f037fe7319f
|
||||||
F ext/jni/src/tests/000-000-sanity.test c3427a0e0ac84d7cbe4c95fdc1cd4b61f9ddcf43443408f3000139478c4dc745
|
F ext/jni/src/tests/000-000-sanity.test c3427a0e0ac84d7cbe4c95fdc1cd4b61f9ddcf43443408f3000139478c4dc745
|
||||||
@@ -2142,8 +2142,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
|||||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||||
P b692eb8ccb2d0645599ad73a8bdacf5df499114244aadeb38aabc580fc4dc7c5
|
P 14ed4c64533622e5faf1aaa59c24885885aad43f1c0d4717773e79440e8e1468
|
||||||
R 99817a8518af3f567a07823f0172a1fb
|
R 631890601bc1abeba3be592d27b2aeb0
|
||||||
U stephan
|
U stephan
|
||||||
Z 276f4a4bca9307a54b6144f3c8e4f323
|
Z 39a1f06f24f0b71c35deac1228d090c6
|
||||||
# Remove this line to create a well-formed Fossil manifest.
|
# Remove this line to create a well-formed Fossil manifest.
|
||||||
|
@@ -1 +1 @@
|
|||||||
14ed4c64533622e5faf1aaa59c24885885aad43f1c0d4717773e79440e8e1468
|
3ee6cc29d2111e7ad90860827c0ea808fdf07bc71defdade7e6794ec4a2a3ce2
|
Reference in New Issue
Block a user