Add the "ota_delta()" feature for delta-compressed updates.
FossilOrigin-Name: c64dcd1788f5cc7db197a0ec4ab0981f34a72c6b
This commit is contained in:
parent
268c0f8844
commit
f8bd49ee22
75
ext/ota/ota8.test
Normal file
75
ext/ota/ota8.test
Normal file
@ -0,0 +1,75 @@
|
||||
# 2014 November 20
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
# Test the ota_delta() feature.
|
||||
#
|
||||
|
||||
if {![info exists testdir]} {
|
||||
set testdir [file join [file dirname [info script]] .. .. test]
|
||||
}
|
||||
source $testdir/tester.tcl
|
||||
set ::testprefix ota8
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE TABLE t1(x, y PRIMARY KEY, z);
|
||||
INSERT INTO t1 VALUES(NULL, 1, 'one');
|
||||
INSERT INTO t1 VALUES(NULL, 2, 'two');
|
||||
INSERT INTO t1 VALUES(NULL, 3, 'three');
|
||||
CREATE INDEX i1z ON t1(z, x);
|
||||
}
|
||||
|
||||
do_test 1.1 {
|
||||
forcedelete ota.db
|
||||
sqlite3 db2 ota.db
|
||||
db2 eval {
|
||||
CREATE TABLE data_t1(x, y, z, ota_control);
|
||||
INSERT INTO data_t1 VALUES('a', 1, '_i' , 'x.d');
|
||||
INSERT INTO data_t1 VALUES('b', 2, 2 , '..x');
|
||||
INSERT INTO data_t1 VALUES('_iii', 3, '-III' , 'd.d');
|
||||
}
|
||||
db2 close
|
||||
} {}
|
||||
|
||||
do_test 1.2.1 {
|
||||
sqlite3ota ota test.db ota.db
|
||||
ota step
|
||||
} {SQLITE_ERROR}
|
||||
do_test 1.2.2 {
|
||||
list [catch {ota close} msg] $msg
|
||||
} {1 {SQLITE_ERROR - no such function: ota_delta}}
|
||||
|
||||
proc ota_delta {orig new} {
|
||||
return "${orig}${new}"
|
||||
}
|
||||
|
||||
do_test 1.3.1 {
|
||||
while 1 {
|
||||
sqlite3ota ota test.db ota.db
|
||||
ota create_ota_delta
|
||||
set rc [ota step]
|
||||
if {$rc != "SQLITE_OK"} break
|
||||
ota close
|
||||
}
|
||||
ota close
|
||||
} {SQLITE_DONE}
|
||||
|
||||
do_execsql_test 1.3.2 {
|
||||
SELECT * FROM t1
|
||||
} {
|
||||
a 1 one_i
|
||||
{} 2 2
|
||||
_iii 3 three-III
|
||||
}
|
||||
integrity_check 1.3.3
|
||||
|
||||
|
||||
finish_test
|
||||
|
@ -447,6 +447,22 @@ static int otaObjIterGetCols(sqlite3ota *p, OtaObjIter *pIter){
|
||||
return p->rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** This is a wrapper around "sqlite3_mprintf(zFmt, ...)". If an OOM occurs,
|
||||
** an error code is stored in the OTA handle passed as the first argument.
|
||||
*/
|
||||
static char *otaMPrintfAndCollectError(sqlite3ota *p, const char *zFmt, ...){
|
||||
char *zSql = 0;
|
||||
va_list ap;
|
||||
va_start(ap, zFmt);
|
||||
if( p->rc==SQLITE_OK ){
|
||||
zSql = sqlite3_vmprintf(zFmt, ap);
|
||||
if( zSql==0 ) p->rc = SQLITE_NOMEM;
|
||||
}
|
||||
va_end(ap);
|
||||
return zSql;
|
||||
}
|
||||
|
||||
/*
|
||||
** This function constructs and returns a pointer to a nul-terminated
|
||||
** string containing some SQL clause or list based on one or more of the
|
||||
@ -570,6 +586,7 @@ static void otaBadControlError(sqlite3ota *p){
|
||||
p->zErrmsg = sqlite3_mprintf("Invalid ota_control value");
|
||||
}
|
||||
|
||||
|
||||
static char *otaObjIterGetSetlist(
|
||||
sqlite3ota *p,
|
||||
OtaObjIter *pIter,
|
||||
@ -584,14 +601,17 @@ static char *otaObjIterGetSetlist(
|
||||
}else{
|
||||
const char *zSep = "";
|
||||
for(i=0; i<pIter->nTblCol; i++){
|
||||
if( zMask[i]=='x' ){
|
||||
zList = sqlite3_mprintf("%z%s%s=?%d",
|
||||
char c = zMask[i];
|
||||
if( c=='x' ){
|
||||
zList = otaMPrintfAndCollectError(p, "%z%s%s=?%d",
|
||||
zList, zSep, pIter->azTblCol[i], i+1
|
||||
);
|
||||
if( zList==0 ){
|
||||
p->rc = SQLITE_NOMEM;
|
||||
break;
|
||||
}
|
||||
zSep = ", ";
|
||||
}
|
||||
if( c=='d' ){
|
||||
zList = otaMPrintfAndCollectError(p, "%z%s%s=ota_delta(%s, ?%d)",
|
||||
zList, zSep, pIter->azTblCol[i], pIter->azTblCol[i], i+1
|
||||
);
|
||||
zSep = ", ";
|
||||
}
|
||||
}
|
||||
@ -1389,6 +1409,13 @@ sqlite3ota *sqlite3ota_open(const char *zTarget, const char *zOta){
|
||||
return p;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the database handle used by pOta.
|
||||
*/
|
||||
sqlite3 *sqlite3ota_db(sqlite3ota *pOta){
|
||||
return (pOta ? pOta->db : 0);
|
||||
}
|
||||
|
||||
/*
|
||||
** Close the OTA handle.
|
||||
*/
|
||||
@ -1450,6 +1477,31 @@ sqlite3_int64 sqlite3ota_progress(sqlite3ota *pOta){
|
||||
/* From main.c (apparently...) */
|
||||
extern const char *sqlite3ErrName(int);
|
||||
|
||||
void test_ota_delta(sqlite3_context *pCtx, int nArg, sqlite3_value **apVal){
|
||||
Tcl_Interp *interp = (Tcl_Interp*)sqlite3_user_data(pCtx);
|
||||
Tcl_Obj *pScript;
|
||||
int i;
|
||||
|
||||
pScript = Tcl_NewObj();
|
||||
Tcl_IncrRefCount(pScript);
|
||||
Tcl_ListObjAppendElement(0, pScript, Tcl_NewStringObj("ota_delta", -1));
|
||||
for(i=0; i<nArg; i++){
|
||||
sqlite3_value *pIn = apVal[i];
|
||||
const char *z = (const char*)sqlite3_value_text(pIn);
|
||||
Tcl_ListObjAppendElement(0, pScript, Tcl_NewStringObj(z, -1));
|
||||
}
|
||||
|
||||
if( TCL_OK==Tcl_EvalObjEx(interp, pScript, TCL_GLOBAL_ONLY) ){
|
||||
const char *z = Tcl_GetStringResult(interp);
|
||||
sqlite3_result_text(pCtx, z, -1, SQLITE_TRANSIENT);
|
||||
}else{
|
||||
Tcl_BackgroundError(interp);
|
||||
}
|
||||
|
||||
Tcl_DecrRefCount(pScript);
|
||||
}
|
||||
|
||||
|
||||
static int test_sqlite3ota_cmd(
|
||||
ClientData clientData,
|
||||
Tcl_Interp *interp,
|
||||
@ -1458,7 +1510,7 @@ static int test_sqlite3ota_cmd(
|
||||
){
|
||||
int ret = TCL_OK;
|
||||
sqlite3ota *pOta = (sqlite3ota*)clientData;
|
||||
const char *azMethod[] = { "step", "close", 0 };
|
||||
const char *azMethod[] = { "step", "close", "create_ota_delta", 0 };
|
||||
int iMethod;
|
||||
|
||||
if( objc!=2 ){
|
||||
@ -1495,6 +1547,16 @@ static int test_sqlite3ota_cmd(
|
||||
break;
|
||||
}
|
||||
|
||||
case 2: /* create_ota_delta */ {
|
||||
sqlite3 *db = sqlite3ota_db(pOta);
|
||||
int rc = sqlite3_create_function(
|
||||
db, "ota_delta", -1, SQLITE_UTF8, (void*)interp, test_ota_delta, 0, 0
|
||||
);
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
|
||||
ret = (rc==SQLITE_OK ? TCL_OK : TCL_ERROR);
|
||||
break;
|
||||
}
|
||||
|
||||
default: /* seems unlikely */
|
||||
assert( !"cannot happen" );
|
||||
break;
|
||||
|
@ -132,6 +132,21 @@
|
||||
**
|
||||
** INSERT INTO data_t1(a, b, c, ota_control) VALUES(4, NULL, 'usa', '..x');
|
||||
**
|
||||
** Instead of an 'x' character, characters of the ota_control value specified
|
||||
** for UPDATEs may also be set to 'd'. In this case, instead of updating the
|
||||
** target table with the value stored in the corresponding data_% column, the
|
||||
** user-defined SQL function "ota_delta()" is invoked and the result stored in
|
||||
** the target table column. ota_delta() is invoked with two arguments - the
|
||||
** original value currently stored in the target table column and the
|
||||
** value specified in the data_xxx table.
|
||||
**
|
||||
** For example, this row:
|
||||
**
|
||||
** INSERT INTO data_t1(a, b, c, ota_control) VALUES(4, NULL, 'usa', '..d');
|
||||
**
|
||||
** is similar to an UPDATE statement such as:
|
||||
**
|
||||
** UPDATE t1 SET c = ota_delta(c, 'usa') WHERE a = 4;
|
||||
**
|
||||
** USAGE
|
||||
**
|
||||
@ -181,6 +196,25 @@ typedef struct sqlite3ota sqlite3ota;
|
||||
*/
|
||||
sqlite3ota *sqlite3ota_open(const char *zTarget, const char *zOta);
|
||||
|
||||
/*
|
||||
** Obtain the underlying database handle used by the OTA extension.
|
||||
**
|
||||
** The only argument passed to this function must be a valid, open, OTA
|
||||
** handle. This function returns the database handle used by OTA for all
|
||||
** operations on the target and source databases. This may be useful in
|
||||
** two scenarios:
|
||||
**
|
||||
** * If the data_xxx tables in the OTA source database are virtual
|
||||
** tables, or if any of the tables being updated are virtual tables,
|
||||
** the application may need to call sqlite3_create_module() on
|
||||
** the db handle to register the required virtual table implementations.
|
||||
**
|
||||
** * If the application uses the "ota_delta()" feature described above,
|
||||
** it must use sqlite3_create_function() or similar to register the
|
||||
** ota_delta() implementation with OTA.
|
||||
*/
|
||||
sqlite3 *sqlite3ota_db(sqlite3ota*);
|
||||
|
||||
/*
|
||||
** Do some work towards applying the OTA update to the target db.
|
||||
**
|
||||
|
15
manifest
15
manifest
@ -1,5 +1,5 @@
|
||||
C Update\sthe\sota\sextension\sso\sthat\sit\scan\sbe\sused\sto\supdate\stables\swith\sexternal\sPRIMARY\sKEY\sindexes.
|
||||
D 2014-11-20T17:37:08.997
|
||||
C Add\sthe\s"ota_delta()"\sfeature\sfor\sdelta-compressed\supdates.
|
||||
D 2014-11-20T19:19:02.502
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in cf57f673d77606ab0f2d9627ca52a9ba1464146a
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
@ -131,9 +131,10 @@ F ext/ota/ota4.test 60f897f329a6782ef2f24862640acf3c52e48077
|
||||
F ext/ota/ota5.test ad0799daf8923ddebffe75ae8c5504ca90b7fadb
|
||||
F ext/ota/ota6.test 82f1f757ec9b2ad07d6de4060b8e3ba8e44dfdd3
|
||||
F ext/ota/ota7.test 1fe2c5761705374530e29f70c39693076028221a
|
||||
F ext/ota/ota8.test cd70e63a0c29c45c0906692827deafa34638feda
|
||||
F ext/ota/otafault.test be02466863015a583cc0ceb6aca871a5e6f7a71b
|
||||
F ext/ota/sqlite3ota.c 2c31a56890e915e13eb5d6ced02325e1f4db7487
|
||||
F ext/ota/sqlite3ota.h 7b20abe9247d292429d00f0a5c237ff6e0dc0196
|
||||
F ext/ota/sqlite3ota.c edeea10871d1307ff9ee9ccc765ba4031b507509
|
||||
F ext/ota/sqlite3ota.h 08b276fc9f56c04cdb454cf7aefa41c29361ed7a
|
||||
F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
|
||||
F ext/rtree/rtree.c 57bec53e1a677ab74217fe1f20a58c3a47261d6b
|
||||
F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e
|
||||
@ -1217,7 +1218,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
|
||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
|
||||
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
||||
P 556c3de53ad33d11d33ec794345c2100aa76f3e1
|
||||
R c3a23811c2315fa65ee1bcdda07f2567
|
||||
P 55066a1171cbd3077f5e6c8ceb2745e810d9476e
|
||||
R 97efd71a02c88dd0da29f19b3d083930
|
||||
U dan
|
||||
Z eebecee2ceb200b37a4bd343197c1b04
|
||||
Z 1557aa5ff604851a6b4517de0e4ff6aa
|
||||
|
@ -1 +1 @@
|
||||
55066a1171cbd3077f5e6c8ceb2745e810d9476e
|
||||
c64dcd1788f5cc7db197a0ec4ab0981f34a72c6b
|
Loading…
Reference in New Issue
Block a user