Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Changes In Branch ota-update Excluding Merge-Ins
This is equivalent to a diff from 5df4056448 to efa20f8e41
2015-05-19
| ||
16:50 | Merge the ota-update branch with trunk. (check-in: 08e2864ed7 user: dan tags: trunk) | |
16:26 | Add a comment for SQLITE_FCNTL_OTA to sqlite.h.in. (Closed-Leaf check-in: efa20f8e41 user: dan tags: ota-update) | |
16:22 | Allow OTA update state data to be stored in a database separate from the OTA update database. (check-in: 5af8db56af user: dan tags: ota-update) | |
14:14 | Merge latest trunk changes with this branch. (check-in: 6055a6725c user: dan tags: ota-update) | |
2015-05-18
| ||
12:28 | Transitive constraints should only work if operands have compatible affinities and collating sequences. (check-in: 5df4056448 user: drh tags: trunk) | |
12:18 | Use an ALWAY() on conditionals in the transitive constraint logic that are always true as far as we know. (Closed-Leaf check-in: 204e567f68 user: drh tags: transitive-constraints) | |
04:24 | Make a hard copy of the results of a subquery lest the result of the subquery be referenced after a change to the table that generated the subquery result. (check-in: 9c0d80907b user: drh tags: trunk) | |
Changes to Makefile.in.
335 335 $(TOP)/ext/fts3/fts3_write.c 336 336 SRC += \ 337 337 $(TOP)/ext/icu/sqliteicu.h \ 338 338 $(TOP)/ext/icu/icu.c 339 339 SRC += \ 340 340 $(TOP)/ext/rtree/rtree.h \ 341 341 $(TOP)/ext/rtree/rtree.c 342 +SRC += \ 343 + $(TOP)/ext/ota/sqlite3ota.h \ 344 + $(TOP)/ext/ota/sqlite3ota.c 342 345 343 346 344 347 # Generated source code files 345 348 # 346 349 SRC += \ 347 350 keywordhash.h \ 348 351 opcodes.c \ ................................................................................ 391 394 $(TOP)/src/test_superlock.c \ 392 395 $(TOP)/src/test_syscall.c \ 393 396 $(TOP)/src/test_tclvar.c \ 394 397 $(TOP)/src/test_thread.c \ 395 398 $(TOP)/src/test_vfs.c \ 396 399 $(TOP)/src/test_wsd.c \ 397 400 $(TOP)/ext/fts3/fts3_term.c \ 398 - $(TOP)/ext/fts3/fts3_test.c 401 + $(TOP)/ext/fts3/fts3_test.c \ 402 + $(TOP)/ext/ota/test_ota.c 399 403 400 404 # Statically linked extensions 401 405 # 402 406 TESTSRC += \ 403 407 $(TOP)/ext/misc/amatch.c \ 404 408 $(TOP)/ext/misc/closure.c \ 405 409 $(TOP)/ext/misc/eval.c \
Added ext/ota/ota.c.
1 +/* 2 +** 2014 August 30 3 +** 4 +** The author disclaims copyright to this source code. In place of 5 +** a legal notice, here is a blessing: 6 +** 7 +** May you do good and not evil. 8 +** May you find forgiveness for yourself and forgive others. 9 +** May you share freely, never taking more than you give. 10 +** 11 +************************************************************************* 12 +** 13 +** This file contains a command-line application that uses the OTA 14 +** extension. See the usage() function below for an explanation. 15 +*/ 16 + 17 +#include "sqlite3ota.h" 18 +#include <stdio.h> 19 +#include <stdlib.h> 20 +#include <string.h> 21 + 22 +/* 23 +** Print a usage message and exit. 24 +*/ 25 +void usage(const char *zArgv0){ 26 + fprintf(stderr, 27 +"Usage: %s [-step NSTEP] TARGET-DB OTA-DB\n" 28 +"\n" 29 +" Argument OTA-DB must be an OTA database containing an update suitable for\n" 30 +" target database TARGET-DB. If NSTEP is set to less than or equal to zero\n" 31 +" (the default value), this program attempts to apply the entire update to\n" 32 +" the target database.\n" 33 +"\n" 34 +" If NSTEP is greater than zero, then a maximum of NSTEP calls are made\n" 35 +" to sqlite3ota_step(). If the OTA update has not been completely applied\n" 36 +" after the NSTEP'th call is made, the state is saved in the database OTA-DB\n" 37 +" and the program exits. Subsequent invocations of this (or any other OTA)\n" 38 +" application will use this state to resume applying the OTA update to the\n" 39 +" target db.\n" 40 +"\n" 41 +, zArgv0); 42 + exit(1); 43 +} 44 + 45 +void report_default_vfs(){ 46 + sqlite3_vfs *pVfs = sqlite3_vfs_find(0); 47 + fprintf(stdout, "default vfs is \"%s\"\n", pVfs->zName); 48 +} 49 + 50 +void report_ota_vfs(sqlite3ota *pOta){ 51 + sqlite3 *db = sqlite3ota_db(pOta, 0); 52 + if( db ){ 53 + char *zName = 0; 54 + sqlite3_file_control(db, "main", SQLITE_FCNTL_VFSNAME, &zName); 55 + if( zName ){ 56 + fprintf(stdout, "using vfs \"%s\"\n", zName); 57 + }else{ 58 + fprintf(stdout, "vfs name not available\n"); 59 + } 60 + sqlite3_free(zName); 61 + } 62 +} 63 + 64 +int main(int argc, char **argv){ 65 + int i; 66 + const char *zTarget; /* Target database to apply OTA to */ 67 + const char *zOta; /* Database containing OTA */ 68 + char *zErrmsg; /* Error message, if any */ 69 + sqlite3ota *pOta; /* OTA handle */ 70 + int nStep = 0; /* Maximum number of step() calls */ 71 + int rc; 72 + sqlite3_int64 nProgress = 0; 73 + 74 + /* Process command line arguments. Following this block local variables 75 + ** zTarget, zOta and nStep are all set. */ 76 + if( argc==5 ){ 77 + int nArg1 = strlen(argv[1]); 78 + if( nArg1>5 || nArg1<2 || memcmp("-step", argv[1], nArg1) ) usage(argv[0]); 79 + nStep = atoi(argv[2]); 80 + }else if( argc!=3 ){ 81 + usage(argv[0]); 82 + } 83 + zTarget = argv[argc-2]; 84 + zOta = argv[argc-1]; 85 + 86 + report_default_vfs(); 87 + 88 + /* Open an OTA handle. If nStep is less than or equal to zero, call 89 + ** sqlite3ota_step() until either the OTA has been completely applied 90 + ** or an error occurs. Or, if nStep is greater than zero, call 91 + ** sqlite3ota_step() a maximum of nStep times. */ 92 + pOta = sqlite3ota_open(zTarget, zOta); 93 + report_ota_vfs(pOta); 94 + for(i=0; (nStep<=0 || i<nStep) && sqlite3ota_step(pOta)==SQLITE_OK; i++); 95 + nProgress = sqlite3ota_progress(pOta); 96 + rc = sqlite3ota_close(pOta, &zErrmsg); 97 + 98 + /* Let the user know what happened. */ 99 + switch( rc ){ 100 + case SQLITE_OK: 101 + fprintf(stdout, 102 + "SQLITE_OK: ota update incomplete (%lld operations so far)\n", 103 + nProgress 104 + ); 105 + break; 106 + 107 + case SQLITE_DONE: 108 + fprintf(stdout, 109 + "SQLITE_DONE: ota update completed (%lld operations)\n", 110 + nProgress 111 + ); 112 + break; 113 + 114 + default: 115 + fprintf(stderr, "error=%d: %s\n", rc, zErrmsg); 116 + break; 117 + } 118 + 119 + sqlite3_free(zErrmsg); 120 + return (rc==SQLITE_OK || rc==SQLITE_DONE) ? 0 : 1; 121 +} 122 +
Added ext/ota/ota1.test.
1 +# 2014 August 30 2 +# 3 +# The author disclaims copyright to this source code. In place of 4 +# a legal notice, here is a blessing: 5 +# 6 +# May you do good and not evil. 7 +# May you find forgiveness for yourself and forgive others. 8 +# May you share freely, never taking more than you give. 9 +# 10 +#*********************************************************************** 11 +# 12 + 13 +if {![info exists testdir]} { 14 + set testdir [file join [file dirname [info script]] .. .. test] 15 +} 16 +source $testdir/tester.tcl 17 +set ::testprefix ota1 18 + 19 +db close 20 +sqlite3_shutdown 21 +sqlite3_config_uri 1 22 + 23 +# Create a simple OTA database. That expects to write to a table: 24 +# 25 +# CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); 26 +# 27 +proc create_ota1 {filename} { 28 + forcedelete $filename 29 + sqlite3 ota1 $filename 30 + ota1 eval { 31 + CREATE TABLE data_t1(a, b, c, ota_control); 32 + INSERT INTO data_t1 VALUES(1, 2, 3, 0); 33 + INSERT INTO data_t1 VALUES(2, 'two', 'three', 0); 34 + INSERT INTO data_t1 VALUES(3, NULL, 8.2, 0); 35 + } 36 + ota1 close 37 + return $filename 38 +} 39 + 40 +# Create a simple OTA database. That expects to write to a table: 41 +# 42 +# CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); 43 +# 44 +# This OTA includes both insert and delete operations. 45 +# 46 +proc create_ota4 {filename} { 47 + forcedelete $filename 48 + sqlite3 ota1 $filename 49 + ota1 eval { 50 + CREATE TABLE data_t1(a, b, c, ota_control); 51 + INSERT INTO data_t1 VALUES(1, 2, 3, 0); 52 + INSERT INTO data_t1 VALUES(2, NULL, 5, 1); 53 + INSERT INTO data_t1 VALUES(3, 8, 9, 0); 54 + INSERT INTO data_t1 VALUES(4, NULL, 11, 1); 55 + } 56 + ota1 close 57 + return $filename 58 +} 59 +# 60 +# Create a simple OTA database. That expects to write to a table: 61 +# 62 +# CREATE TABLE t1(c, b, '(a)' INTEGER PRIMARY KEY); 63 +# 64 +# This OTA includes both insert and delete operations. 65 +# 66 +proc create_ota4b {filename} { 67 + forcedelete $filename 68 + sqlite3 ota1 $filename 69 + ota1 eval { 70 + CREATE TABLE data_t1(c, b, '(a)', ota_control); 71 + INSERT INTO data_t1 VALUES(3, 2, 1, 0); 72 + INSERT INTO data_t1 VALUES(5, NULL, 2, 1); 73 + INSERT INTO data_t1 VALUES(9, 8, 3, 0); 74 + INSERT INTO data_t1 VALUES(11, NULL, 4, 1); 75 + } 76 + ota1 close 77 + return $filename 78 +} 79 + 80 +# Create a simple OTA database. That expects to write to a table: 81 +# 82 +# CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, d); 83 +# 84 +# This OTA includes update statements. 85 +# 86 +proc create_ota5 {filename} { 87 + forcedelete $filename 88 + sqlite3 ota5 $filename 89 + ota5 eval { 90 + CREATE TABLE data_t1(a, b, c, d, ota_control); 91 + INSERT INTO data_t1 VALUES(1, NULL, NULL, 5, '...x'); -- SET d = 5 92 + INSERT INTO data_t1 VALUES(2, NULL, 10, 5, '..xx'); -- SET c=10, d = 5 93 + INSERT INTO data_t1 VALUES(3, 11, NULL, NULL, '.x..'); -- SET b=11 94 + } 95 + ota5 close 96 + return $filename 97 +} 98 + 99 +# Run the OTA in file $ota on target database $target until completion. 100 +# 101 +proc run_ota {target ota} { 102 + sqlite3ota ota $target $ota 103 + while 1 { 104 + set rc [ota step] 105 + if {$rc!="SQLITE_OK"} break 106 + } 107 + ota close 108 +} 109 + 110 +proc step_ota {target ota} { 111 + while 1 { 112 + sqlite3ota ota $target $ota 113 + set rc [ota step] 114 + ota close 115 + if {$rc != "SQLITE_OK"} break 116 + } 117 + set rc 118 +} 119 + 120 +# Same as [step_ota], except using a URI to open the target db. 121 +# 122 +proc step_ota_uri {target ota} { 123 + while 1 { 124 + sqlite3ota ota file:$target?xyz=&abc=123 $ota 125 + set rc [ota step] 126 + ota close 127 + if {$rc != "SQLITE_OK"} break 128 + } 129 + set rc 130 +} 131 + 132 +# Same as [step_ota], except using an external state database - "state.db" 133 +# 134 +proc step_ota_state {target ota} { 135 + while 1 { 136 + sqlite3ota ota $target $ota state.db 137 + set rc [ota step] 138 + ota close 139 + if {$rc != "SQLITE_OK"} break 140 + } 141 + set rc 142 +} 143 + 144 +proc dbfilecksum {file} { 145 + sqlite3 ck $file 146 + set cksum [dbcksum ck main] 147 + ck close 148 + set cksum 149 +} 150 + 151 +foreach {tn3 create_vfs destroy_vfs} { 152 + 1 {} {} 153 + 2 { 154 + sqlite3ota_create_vfs -default myota "" 155 + } { 156 + sqlite3ota_destroy_vfs myota 157 + } 158 +} { 159 + 160 + eval $create_vfs 161 + 162 + foreach {tn2 cmd} { 163 + 1 run_ota 164 + 2 step_ota 3 step_ota_uri 4 step_ota_state 165 + } { 166 + foreach {tn schema} { 167 + 1 { 168 + CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); 169 + } 170 + 2 { 171 + CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); 172 + CREATE INDEX i1 ON t1(b); 173 + } 174 + 3 { 175 + CREATE TABLE t1(a PRIMARY KEY, b, c) WITHOUT ROWID; 176 + } 177 + 4 { 178 + CREATE TABLE t1(a PRIMARY KEY, b, c) WITHOUT ROWID; 179 + CREATE INDEX i1 ON t1(b); 180 + } 181 + 5 { 182 + CREATE TABLE t1(a, b, c, PRIMARY KEY(a, c)) WITHOUT ROWID; 183 + CREATE INDEX i1 ON t1(b); 184 + } 185 + 6 { 186 + CREATE TABLE t1(a, b, c, PRIMARY KEY(c)) WITHOUT ROWID; 187 + CREATE INDEX i1 ON t1(b, a); 188 + } 189 + 7 { 190 + CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); 191 + CREATE INDEX i1 ON t1(b, c); 192 + CREATE INDEX i2 ON t1(c, b); 193 + CREATE INDEX i3 ON t1(a, b, c, a, b, c); 194 + } 195 + 196 + 8 { 197 + CREATE TABLE t1(a PRIMARY KEY, b, c); 198 + CREATE INDEX i1 ON t1(b, c); 199 + CREATE INDEX i2 ON t1(c, b); 200 + CREATE INDEX i3 ON t1(a, b, c, a, b, c); 201 + } 202 + 203 + 9 { 204 + CREATE TABLE t1(a, b, c, PRIMARY KEY(a, c)); 205 + CREATE INDEX i1 ON t1(b); 206 + } 207 + 208 + 10 { 209 + CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); 210 + CREATE INDEX i1 ON t1(b DESC); 211 + } 212 + 213 + 11 { 214 + CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); 215 + CREATE INDEX i1 ON t1(b DESC, a ASC, c DESC); 216 + } 217 + 218 + 12 { 219 + CREATE TABLE t1(a INT PRIMARY KEY DESC, b, c) WITHOUT ROWID; 220 + } 221 + 222 + 13 { 223 + CREATE TABLE t1(a INT, b, c, PRIMARY KEY(a DESC)) WITHOUT ROWID; 224 + } 225 + 226 + 14 { 227 + CREATE TABLE t1(a, b, c, PRIMARY KEY(a DESC, c)) WITHOUT ROWID; 228 + CREATE INDEX i1 ON t1(b); 229 + } 230 + 231 + 15 { 232 + CREATE TABLE t1(a, b, c, PRIMARY KEY(a, c DESC)) WITHOUT ROWID; 233 + CREATE INDEX i1 ON t1(b); 234 + } 235 + 236 + 16 { 237 + CREATE TABLE t1(a, b, c, PRIMARY KEY(c DESC, a)) WITHOUT ROWID; 238 + CREATE INDEX i1 ON t1(b DESC, c, a); 239 + } 240 + } { 241 + reset_db 242 + execsql $schema 243 + create_ota1 ota.db 244 + set check [dbfilecksum ota.db] 245 + forcedelete state.db 246 + 247 + do_test $tn3.1.$tn2.$tn.1 { 248 + $cmd test.db ota.db 249 + } {SQLITE_DONE} 250 + 251 + do_execsql_test $tn3.1.$tn2.$tn.2 { SELECT * FROM t1 ORDER BY a ASC } { 252 + 1 2 3 253 + 2 two three 254 + 3 {} 8.2 255 + } 256 + do_execsql_test $tn3.1.$tn2.$tn.3 { SELECT * FROM t1 ORDER BY b ASC } { 257 + 3 {} 8.2 258 + 1 2 3 259 + 2 two three 260 + } 261 + do_execsql_test $tn3.1.$tn2.$tn.4 { SELECT * FROM t1 ORDER BY c ASC } { 262 + 1 2 3 263 + 3 {} 8.2 264 + 2 two three 265 + } 266 + 267 + do_execsql_test $tn3.1.$tn2.$tn.5 { PRAGMA integrity_check } ok 268 + 269 + if {$cmd=="step_ota_state"} { 270 + do_test $tn3.1.$tn2.$tn.6 { file exists state.db } 1 271 + do_test $tn3.1.$tn2.$tn.7 { expr {$check == [dbfilecksum ota.db]} } 1 272 + } else { 273 + do_test $tn3.1.$tn2.$tn.8 { file exists state.db } 0 274 + do_test $tn3.1.$tn2.$tn.9 { expr {$check == [dbfilecksum ota.db]} } 0 275 + } 276 + } 277 + } 278 + 279 + #------------------------------------------------------------------------- 280 + # Check that an OTA cannot be applied to a table that has no PK. 281 + # 282 + # UPDATE: At one point OTA required that all tables featured either 283 + # explicit IPK columns or were declared WITHOUT ROWID. This has been 284 + # relaxed so that external PRIMARY KEYs on tables with automatic rowids 285 + # are now allowed. 286 + # 287 + # UPDATE 2: Tables without any PRIMARY KEY declaration are now allowed. 288 + # However the input table must feature an "ota_rowid" column. 289 + # 290 + reset_db 291 + create_ota1 ota.db 292 + do_execsql_test $tn3.2.1 { CREATE TABLE t1(a, b, c) } 293 + do_test $tn3.2.2 { 294 + sqlite3ota ota test.db ota.db 295 + ota step 296 + } {SQLITE_ERROR} 297 + do_test $tn3.2.3 { 298 + list [catch { ota close } msg] $msg 299 + } {1 {SQLITE_ERROR - table data_t1 requires ota_rowid column}} 300 + reset_db 301 + do_execsql_test $tn3.2.4 { CREATE TABLE t1(a PRIMARY KEY, b, c) } 302 + do_test $tn3.2.5 { 303 + sqlite3ota ota test.db ota.db 304 + ota step 305 + } {SQLITE_OK} 306 + do_test $tn3.2.6 { 307 + list [catch { ota close } msg] $msg 308 + } {0 SQLITE_OK} 309 + 310 + #------------------------------------------------------------------------- 311 + # Check that if a UNIQUE constraint is violated the current and all 312 + # subsequent [ota step] calls return SQLITE_CONSTRAINT. And that the OTA 313 + # transaction is rolled back by the [ota close] that deletes the ota 314 + # handle. 315 + # 316 + foreach {tn errcode errmsg schema} { 317 + 1 SQLITE_CONSTRAINT "UNIQUE constraint failed: t1.a" { 318 + CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); 319 + INSERT INTO t1 VALUES(3, 2, 1); 320 + } 321 + 322 + 2 SQLITE_CONSTRAINT "UNIQUE constraint failed: t1.c" { 323 + CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c UNIQUE); 324 + INSERT INTO t1 VALUES(4, 2, 'three'); 325 + } 326 + 327 + 3 SQLITE_CONSTRAINT "UNIQUE constraint failed: t1.a" { 328 + CREATE TABLE t1(a PRIMARY KEY, b, c); 329 + INSERT INTO t1 VALUES(3, 2, 1); 330 + } 331 + 332 + 4 SQLITE_CONSTRAINT "UNIQUE constraint failed: t1.c" { 333 + CREATE TABLE t1(a PRIMARY KEY, b, c UNIQUE); 334 + INSERT INTO t1 VALUES(4, 2, 'three'); 335 + } 336 + 337 + } { 338 + reset_db 339 + execsql $schema 340 + set cksum [dbcksum db main] 341 + 342 + do_test $tn3.3.$tn.1 { 343 + create_ota1 ota.db 344 + sqlite3ota ota test.db ota.db 345 + while {[set res [ota step]]=="SQLITE_OK"} {} 346 + set res 347 + } $errcode 348 + 349 + do_test $tn3.3.$tn.2 { ota step } $errcode 350 + 351 + do_test $tn3.3.$tn.3 { 352 + list [catch { ota close } msg] $msg 353 + } [list 1 "$errcode - $errmsg"] 354 + 355 + do_test $tn3.3.$tn.4 { dbcksum db main } $cksum 356 + } 357 + 358 + #------------------------------------------------------------------------- 359 + # 360 + foreach {tn2 cmd} {1 run_ota 2 step_ota 3 step_ota_state } { 361 + foreach {tn schema} { 362 + 1 { 363 + CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); 364 + } 365 + 2 { 366 + CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); 367 + CREATE INDEX i1 ON t1(b); 368 + } 369 + 3 { 370 + CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); 371 + CREATE INDEX i1 ON t1(b); 372 + CREATE INDEX i2 ON t1(c, b); 373 + CREATE INDEX i3 ON t1(c, b, c); 374 + } 375 + 4 { 376 + CREATE TABLE t1(a INT PRIMARY KEY, b, c) WITHOUT ROWID; 377 + CREATE INDEX i1 ON t1(b); 378 + CREATE INDEX i2 ON t1(c, b); 379 + CREATE INDEX i3 ON t1(c, b, c); 380 + } 381 + 5 { 382 + CREATE TABLE t1(a INT PRIMARY KEY, b, c); 383 + CREATE INDEX i1 ON t1(b); 384 + CREATE INDEX i2 ON t1(c, b); 385 + CREATE INDEX i3 ON t1(c, b, c); 386 + } 387 + 388 + 6 { 389 + CREATE TABLE t1(a INT PRIMARY KEY DESC, b, c); 390 + CREATE INDEX i1 ON t1(b DESC); 391 + CREATE INDEX i2 ON t1(c, b); 392 + CREATE INDEX i3 ON t1(c DESC, b, c); 393 + } 394 + 7 { 395 + CREATE TABLE t1(a INT PRIMARY KEY DESC, b, c) WITHOUT ROWID; 396 + CREATE INDEX i1 ON t1(b); 397 + CREATE INDEX i2 ON t1(c, b); 398 + CREATE INDEX i3 ON t1(c, b, c); 399 + } 400 + } { 401 + reset_db 402 + execsql $schema 403 + execsql { 404 + INSERT INTO t1 VALUES(2, 'hello', 'world'); 405 + INSERT INTO t1 VALUES(4, 'hello', 'planet'); 406 + INSERT INTO t1 VALUES(6, 'hello', 'xyz'); 407 + } 408 + 409 + create_ota4 ota.db 410 + set check [dbfilecksum ota.db] 411 + forcedelete state.db 412 + 413 + do_test $tn3.4.$tn2.$tn.1 { 414 + $cmd test.db ota.db 415 + } {SQLITE_DONE} 416 + 417 + do_execsql_test $tn3.4.$tn2.$tn.2 { 418 + SELECT * FROM t1 ORDER BY a ASC; 419 + } { 420 + 1 2 3 421 + 3 8 9 422 + 6 hello xyz 423 + } 424 + 425 + do_execsql_test $tn3.4.$tn2.$tn.3 { PRAGMA integrity_check } ok 426 + 427 + if {$cmd=="step_ota_state"} { 428 + do_test $tn3.4.$tn2.$tn.4 { file exists state.db } 1 429 + do_test $tn3.4.$tn2.$tn.5 { expr {$check == [dbfilecksum ota.db]} } 1 430 + } else { 431 + do_test $tn3.4.$tn2.$tn.6 { file exists state.db } 0 432 + do_test $tn3.4.$tn2.$tn.7 { expr {$check == [dbfilecksum ota.db]} } 0 433 + } 434 + } 435 + } 436 + 437 + foreach {tn2 cmd} {1 run_ota 2 step_ota 3 step_ota_state} { 438 + foreach {tn schema} { 439 + 1 { 440 + CREATE TABLE t1(c, b, '(a)' INTEGER PRIMARY KEY); 441 + CREATE INDEX i1 ON t1(c, b); 442 + } 443 + 2 { 444 + CREATE TABLE t1(c, b, '(a)' PRIMARY KEY); 445 + } 446 + 3 { 447 + CREATE TABLE t1(c, b, '(a)' PRIMARY KEY) WITHOUT ROWID; 448 + } 449 + } { 450 + reset_db 451 + execsql $schema 452 + execsql { 453 + INSERT INTO t1('(a)', b, c) VALUES(2, 'hello', 'world'); 454 + INSERT INTO t1('(a)', b, c) VALUES(4, 'hello', 'planet'); 455 + INSERT INTO t1('(a)', b, c) VALUES(6, 'hello', 'xyz'); 456 + } 457 + 458 + create_ota4b ota.db 459 + set check [dbfilecksum ota.db] 460 + forcedelete state.db 461 + 462 + do_test $tn3.5.$tn2.$tn.1 { 463 + $cmd test.db ota.db 464 + } {SQLITE_DONE} 465 + 466 + do_execsql_test $tn3.5.$tn2.$tn.2 { 467 + SELECT * FROM t1 ORDER BY "(a)" ASC; 468 + } { 469 + 3 2 1 470 + 9 8 3 471 + xyz hello 6 472 + } 473 + 474 + do_execsql_test $tn3.4.$tn2.$tn.3 { PRAGMA integrity_check } ok 475 + 476 + if {$cmd=="step_ota_state"} { 477 + do_test $tn3.5.$tn2.$tn.4 { file exists state.db } 1 478 + do_test $tn3.5.$tn2.$tn.5 { expr {$check == [dbfilecksum ota.db]} } 1 479 + } else { 480 + do_test $tn3.5.$tn2.$tn.6 { file exists state.db } 0 481 + do_test $tn3.5.$tn2.$tn.7 { expr {$check == [dbfilecksum ota.db]} } 0 482 + } 483 + } 484 + } 485 + 486 + #------------------------------------------------------------------------- 487 + # 488 + foreach {tn2 cmd} {1 run_ota 2 step_ota 3 step_ota_state} { 489 + foreach {tn schema} { 490 + 1 { 491 + CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, d); 492 + } 493 + 2 { 494 + CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, d); 495 + CREATE INDEX i1 ON t1(d); 496 + CREATE INDEX i2 ON t1(d, c); 497 + CREATE INDEX i3 ON t1(d, c, b); 498 + CREATE INDEX i4 ON t1(b); 499 + CREATE INDEX i5 ON t1(c); 500 + CREATE INDEX i6 ON t1(c, b); 501 + } 502 + 3 { 503 + CREATE TABLE t1(a PRIMARY KEY, b, c, d) WITHOUT ROWID; 504 + CREATE INDEX i1 ON t1(d); 505 + CREATE INDEX i2 ON t1(d, c); 506 + CREATE INDEX i3 ON t1(d, c, b); 507 + CREATE INDEX i4 ON t1(b); 508 + CREATE INDEX i5 ON t1(c); 509 + CREATE INDEX i6 ON t1(c, b); 510 + } 511 + 4 { 512 + CREATE TABLE t1(a PRIMARY KEY, b, c, d); 513 + CREATE INDEX i1 ON t1(d); 514 + CREATE INDEX i2 ON t1(d, c); 515 + CREATE INDEX i3 ON t1(d, c, b); 516 + CREATE INDEX i4 ON t1(b); 517 + CREATE INDEX i5 ON t1(c); 518 + CREATE INDEX i6 ON t1(c, b); 519 + } 520 + } { 521 + reset_db 522 + execsql $schema 523 + execsql { 524 + INSERT INTO t1 VALUES(1, 2, 3, 4); 525 + INSERT INTO t1 VALUES(2, 5, 6, 7); 526 + INSERT INTO t1 VALUES(3, 8, 9, 10); 527 + } 528 + 529 + create_ota5 ota.db 530 + set check [dbfilecksum ota.db] 531 + forcedelete state.db 532 + 533 + do_test $tn3.5.$tn2.$tn.1 { 534 + $cmd test.db ota.db 535 + } {SQLITE_DONE} 536 + 537 + do_execsql_test $tn3.5.$tn2.$tn.2 { 538 + SELECT * FROM t1 ORDER BY a ASC; 539 + } { 540 + 1 2 3 5 541 + 2 5 10 5 542 + 3 11 9 10 543 + } 544 + 545 + do_execsql_test $tn3.6.$tn2.$tn.3 { PRAGMA integrity_check } ok 546 + 547 + if {$cmd=="step_ota_state"} { 548 + do_test $tn3.6.$tn2.$tn.4 { file exists state.db } 1 549 + do_test $tn3.6.$tn2.$tn.5 { expr {$check == [dbfilecksum ota.db]} } 1 550 + } else { 551 + do_test $tn3.6.$tn2.$tn.6 { file exists state.db } 0 552 + do_test $tn3.6.$tn2.$tn.7 { expr {$check == [dbfilecksum ota.db]} } 0 553 + } 554 + } 555 + } 556 + 557 + #------------------------------------------------------------------------- 558 + # Test some error cases: 559 + # 560 + # * A virtual table with no ota_rowid column. 561 + # * A no-PK table with no ota_rowid column. 562 + # * A PK table with an ota_rowid column. 563 + # 564 + # 6: An update string of the wrong length 565 + # 566 + ifcapable fts3 { 567 + foreach {tn schema error} { 568 + 1 { 569 + CREATE TABLE t1(a, b); 570 + CREATE TABLE ota.data_t1(a, b, ota_control); 571 + } {SQLITE_ERROR - table data_t1 requires ota_rowid column} 572 + 573 + 2 { 574 + CREATE VIRTUAL TABLE t1 USING fts4(a, b); 575 + CREATE TABLE ota.data_t1(a, b, ota_control); 576 + } {SQLITE_ERROR - table data_t1 requires ota_rowid column} 577 + 578 + 3 { 579 + CREATE TABLE t1(a PRIMARY KEY, b); 580 + CREATE TABLE ota.data_t1(a, b, ota_rowid, ota_control); 581 + } {SQLITE_ERROR - table data_t1 may not have ota_rowid column} 582 + 583 + 4 { 584 + CREATE TABLE t1(a INTEGER PRIMARY KEY, b); 585 + CREATE TABLE ota.data_t1(a, b, ota_rowid, ota_control); 586 + } {SQLITE_ERROR - table data_t1 may not have ota_rowid column} 587 + 588 + 5 { 589 + CREATE TABLE t1(a, b PRIMARY KEY) WITHOUT ROWID; 590 + CREATE TABLE ota.data_t1(a, b, ota_rowid, ota_control); 591 + } {SQLITE_ERROR - table data_t1 may not have ota_rowid column} 592 + 593 + 6 { 594 + CREATE TABLE t1(a, b PRIMARY KEY) WITHOUT ROWID; 595 + CREATE TABLE ota.data_t1(a, b, ota_control); 596 + INSERT INTO ota.data_t1 VALUES(1, 2, 'x.x'); 597 + } {SQLITE_ERROR - invalid ota_control value} 598 + 599 + 7 { 600 + CREATE TABLE t1(a, b PRIMARY KEY) WITHOUT ROWID; 601 + CREATE TABLE ota.data_t1(a, b, ota_control); 602 + INSERT INTO ota.data_t1 VALUES(1, 2, NULL); 603 + } {SQLITE_ERROR - invalid ota_control value} 604 + 605 + 8 { 606 + CREATE TABLE t1(a, b PRIMARY KEY) WITHOUT ROWID; 607 + CREATE TABLE ota.data_t1(a, b, ota_control); 608 + INSERT INTO ota.data_t1 VALUES(1, 2, 4); 609 + } {SQLITE_ERROR - invalid ota_control value} 610 + 611 + 9 { 612 + CREATE TABLE t1(a, b PRIMARY KEY) WITHOUT ROWID; 613 + CREATE TABLE ota.data_t1(a, b, ota_control); 614 + INSERT INTO ota.data_t1 VALUES(1, 2, 2); 615 + } {SQLITE_ERROR - invalid ota_control value} 616 + 617 + 10 { 618 + CREATE TABLE t2(a, b); 619 + CREATE TABLE ota.data_t1(a, b, ota_control); 620 + INSERT INTO ota.data_t1 VALUES(1, 2, 2); 621 + } {SQLITE_ERROR - no such table: t1} 622 + 623 + 11 { 624 + CREATE TABLE ota.data_t2(a, b, ota_control); 625 + INSERT INTO ota.data_t2 VALUES(1, 2, 2); 626 + } {SQLITE_ERROR - no such table: t2} 627 + 628 + } { 629 + reset_db 630 + forcedelete ota.db 631 + execsql { ATTACH 'ota.db' AS ota } 632 + execsql $schema 633 + 634 + do_test $tn3.7.$tn { 635 + list [catch { run_ota test.db ota.db } msg] $msg 636 + } [list 1 $error] 637 + } 638 + } 639 + 640 + # Test that an OTA database containing no input tables is handled 641 + # correctly. 642 + reset_db 643 + forcedelete ota.db 644 + do_test $tn3.8 { 645 + list [catch { run_ota test.db ota.db } msg] $msg 646 + } {0 SQLITE_DONE} 647 + 648 + # Test that OTA can update indexes containing NULL values. 649 + # 650 + reset_db 651 + forcedelete ota.db 652 + do_execsql_test $tn3.9.1 { 653 + CREATE TABLE t1(a PRIMARY KEY, b, c); 654 + CREATE INDEX i1 ON t1(b, c); 655 + INSERT INTO t1 VALUES(1, 1, NULL); 656 + INSERT INTO t1 VALUES(2, NULL, 2); 657 + INSERT INTO t1 VALUES(3, NULL, NULL); 658 + 659 + ATTACH 'ota.db' AS ota; 660 + CREATE TABLE ota.data_t1(a, b, c, ota_control); 661 + INSERT INTO data_t1 VALUES(1, NULL, NULL, 1); 662 + INSERT INTO data_t1 VALUES(3, NULL, NULL, 1); 663 + } {} 664 + 665 + do_test $tn3.9.2 { 666 + list [catch { run_ota test.db ota.db } msg] $msg 667 + } {0 SQLITE_DONE} 668 + 669 + do_execsql_test $tn3.9.3 { 670 + SELECT * FROM t1 671 + } {2 {} 2} 672 + do_execsql_test $tn3.9.4 { PRAGMA integrity_check } {ok} 673 + 674 + catch { db close } 675 + eval $destroy_vfs 676 +} 677 + 678 + 679 +finish_test 680 +
Added ext/ota/ota10.test.
1 +# 2014 August 30 2 +# 3 +# The author disclaims copyright to this source code. In place of 4 +# a legal notice, here is a blessing: 5 +# 6 +# May you do good and not evil. 7 +# May you find forgiveness for yourself and forgive others. 8 +# May you share freely, never taking more than you give. 9 +# 10 +#*********************************************************************** 11 +# 12 + 13 +if {![info exists testdir]} { 14 + set testdir [file join [file dirname [info script]] .. .. test] 15 +} 16 +source $testdir/tester.tcl 17 +set ::testprefix ota10 18 + 19 + 20 +#-------------------------------------------------------------------- 21 +# Test that UPDATE commands work even if the input columns are in a 22 +# different order to the output columns. 23 +# 24 +do_execsql_test 1.0 { 25 + CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); 26 + INSERT INTO t1 VALUES(1, 'b', 'c'); 27 +} 28 + 29 +proc apply_ota {sql} { 30 + forcedelete ota.db 31 + sqlite3 db2 ota.db 32 + db2 eval $sql 33 + db2 close 34 + sqlite3ota ota test.db ota.db 35 + while { [ota step]=="SQLITE_OK" } {} 36 + ota close 37 +} 38 + 39 +do_test 1.1 { 40 + apply_ota { 41 + CREATE TABLE data_t1(a, c, b, ota_control); 42 + INSERT INTO data_t1 VALUES(1, 'xxx', NULL, '.x.'); 43 + } 44 + db eval { SELECT * FROM t1 } 45 +} {1 b xxx} 46 + 47 +#-------------------------------------------------------------------- 48 +# Test that the hidden languageid column of an fts4 table can be 49 +# written. 50 +# 51 +ifcapable fts3 { 52 + do_execsql_test 2.0 { 53 + CREATE VIRTUAL TABLE ft USING fts4(a, b, languageid='langid'); 54 + } 55 + do_test 2.1 { 56 + apply_ota { 57 + CREATE TABLE data_ft(a, b, ota_rowid, langid, ota_control); 58 + INSERT INTO data_ft VALUES('a', 'b', 22, 1, 0); -- insert 59 + INSERT INTO data_ft VALUES('a', 'b', 23, 10, 0); -- insert 60 + INSERT INTO data_ft VALUES('a', 'b', 24, 100, 0); -- insert 61 + } 62 + db eval { SELECT a, b, rowid, langid FROM ft } 63 + } [list {*}{ 64 + a b 22 1 65 + a b 23 10 66 + a b 24 100 67 + }] 68 + 69 + # Or not - this data_xxx table has no langid column, so langid 70 + # defaults to 0. 71 + # 72 + do_test 2.2 { 73 + apply_ota { 74 + CREATE TABLE data_ft(a, b, ota_rowid, ota_control); 75 + INSERT INTO data_ft VALUES('a', 'b', 25, 0); -- insert 76 + } 77 + db eval { SELECT a, b, rowid, langid FROM ft } 78 + } [list {*}{ 79 + a b 22 1 80 + a b 23 10 81 + a b 24 100 82 + a b 25 0 83 + }] 84 + 85 + # Update langid. 86 + # 87 + do_test 2.3 { 88 + apply_ota { 89 + CREATE TABLE data_ft(a, b, ota_rowid, langid, ota_control); 90 + INSERT INTO data_ft VALUES(NULL, NULL, 23, 50, '..x'); 91 + INSERT INTO data_ft VALUES(NULL, NULL, 25, 500, '..x'); 92 + } 93 + db eval { SELECT a, b, rowid, langid FROM ft } 94 + } [list {*}{ 95 + a b 22 1 96 + a b 23 50 97 + a b 24 100 98 + a b 25 500 99 + }] 100 +} 101 + 102 +#-------------------------------------------------------------------- 103 +# Test that if writing a hidden virtual table column is an error, 104 +# attempting to do so via ota is also an error. 105 +# 106 +ifcapable fts3 { 107 + do_execsql_test 3.0 { 108 + CREATE VIRTUAL TABLE xt USING fts4(a); 109 + } 110 + do_test 3.1 { 111 + list [catch { 112 + apply_ota { 113 + CREATE TABLE data_xt(a, xt, ota_rowid, ota_control); 114 + INSERT INTO data_xt VALUES('a', 'b', 1, 0); 115 + } 116 + } msg] $msg 117 + } {1 {SQLITE_ERROR - SQL logic error or missing database}} 118 +} 119 + 120 +#-------------------------------------------------------------------- 121 +# Test that it is not possible to violate a NOT NULL constraint by 122 +# applying an OTA update. 123 +# 124 +do_execsql_test 4.1 { 125 + CREATE TABLE t2(a INTEGER NOT NULL, b TEXT NOT NULL, c PRIMARY KEY); 126 + CREATE TABLE t3(a INTEGER NOT NULL, b TEXT NOT NULL, c INTEGER PRIMARY KEY); 127 + CREATE TABLE t4(a, b, PRIMARY KEY(a, b)) WITHOUT ROWID; 128 + 129 + INSERT INTO t2 VALUES(10, 10, 10); 130 + INSERT INTO t3 VALUES(10, 10, 10); 131 + INSERT INTO t4 VALUES(10, 10); 132 +} 133 + 134 +foreach {tn error ota} { 135 + 2 {SQLITE_CONSTRAINT - NOT NULL constraint failed: t2.a} { 136 + INSERT INTO data_t2 VALUES(NULL, 'abc', 1, 0); 137 + } 138 + 3 {SQLITE_CONSTRAINT - NOT NULL constraint failed: t2.b} { 139 + INSERT INTO data_t2 VALUES(2, NULL, 1, 0); 140 + } 141 + 4 {SQLITE_CONSTRAINT - NOT NULL constraint failed: t2.c} { 142 + INSERT INTO data_t2 VALUES(1, 'abc', NULL, 0); 143 + } 144 + 145 + 5 {SQLITE_MISMATCH - datatype mismatch} { 146 + INSERT INTO data_t3 VALUES(1, 'abc', NULL, 0); 147 + } 148 + 149 + 6 {SQLITE_CONSTRAINT - NOT NULL constraint failed: t4.b} { 150 + INSERT INTO data_t4 VALUES('a', NULL, 0); 151 + } 152 + 7 {SQLITE_CONSTRAINT - NOT NULL constraint failed: t4.a} { 153 + INSERT INTO data_t4 VALUES(NULL, 'a', 0); 154 + } 155 + 8 {SQLITE_CONSTRAINT - NOT NULL constraint failed: t2.a} { 156 + INSERT INTO data_t2 VALUES(NULL, 0, 10, 'x..'); 157 + } 158 + 9 {SQLITE_CONSTRAINT - NOT NULL constraint failed: t3.b} { 159 + INSERT INTO data_t3 VALUES(10, NULL, 10, '.x.'); 160 + } 161 + 162 + 10 {SQLITE_MISMATCH - datatype mismatch} { 163 + INSERT INTO data_t3 VALUES(1, 'abc', 'text', 0); 164 + } 165 +} { 166 + set ota " 167 + CREATE TABLE data_t2(a, b, c, ota_control); 168 + CREATE TABLE data_t3(a, b, c, ota_control); 169 + CREATE TABLE data_t4(a, b, ota_control); 170 + $ota 171 + " 172 + do_test 4.2.$tn { 173 + list [catch { apply_ota $ota } msg] $msg 174 + } [list 1 $error] 175 +} 176 + 177 +do_test 4.3 { 178 + set ota { 179 + CREATE TABLE data_t3(a, b, c, ota_control); 180 + INSERT INTO data_t3 VALUES(1, 'abc', '5', 0); 181 + INSERT INTO data_t3 VALUES(1, 'abc', '-6.0', 0); 182 + } 183 + list [catch { apply_ota $ota } msg] $msg 184 +} {0 SQLITE_DONE} 185 + 186 + 187 +finish_test 188 +
Added ext/ota/ota11.test.
1 +# 2015 February 16 2 +# 3 +# The author disclaims copyright to this source code. In place of 4 +# a legal notice, here is a blessing: 5 +# 6 +# May you do good and not evil. 7 +# May you find forgiveness for yourself and forgive others. 8 +# May you share freely, never taking more than you give. 9 +# 10 +#*********************************************************************** 11 +# 12 + 13 +if {![info exists testdir]} { 14 + set testdir [file join [file dirname [info script]] .. .. test] 15 +} 16 +source $testdir/tester.tcl 17 +set ::testprefix ota11 18 + 19 + 20 +#-------------------------------------------------------------------- 21 +# Test that the xAccess() method of an ota vfs handles queries other 22 +# than SQLITE_ACCESS_EXISTS correctly. The test code below causes 23 +# SQLite to call xAccess(SQLITE_ACCESS_READWRITE) on the directory 24 +# path argument passed to "PRAGMA temp_store_directory". 25 +# 26 +do_test 1.1 { 27 + sqlite3ota_create_vfs -default ota "" 28 + reset_db 29 + catchsql { PRAGMA temp_store_directory = '/no/such/directory' } 30 +} {1 {not a writable directory}} 31 + 32 +do_test 1.2 { 33 + catchsql " PRAGMA temp_store_directory = '[pwd]' " 34 +} {0 {}} 35 + 36 +do_test 1.3 { 37 + catchsql " PRAGMA temp_store_directory = '' " 38 +} {0 {}} 39 + 40 +do_test 1.4 { 41 + db close 42 + sqlite3ota_destroy_vfs ota 43 +} {} 44 + 45 +#-------------------------------------------------------------------- 46 +# Try to trick ota into operating on a database opened in wal mode. 47 +# 48 +reset_db 49 +do_execsql_test 2.1 { 50 + CREATE TABLE t1(a PRIMARY KEY, b, c); 51 + INSERT INTO t1 VALUES(1, 2, 3); 52 + PRAGMA journal_mode = 'wal'; 53 + CREATE TABLE t2(d PRIMARY KEY, e, f); 54 +} {wal} 55 + 56 +do_test 2.2 { 57 + db_save 58 + db close 59 + 60 + forcedelete ota.db 61 + sqlite3 dbo ota.db 62 + dbo eval { 63 + CREATE TABLE data_t1(a, b, c, ota_control); 64 + INSERT INTO data_t1 VALUES(4, 5, 6, 0); 65 + INSERT INTO data_t1 VALUES(7, 8, 9, 0); 66 + } 67 + dbo close 68 + 69 + db_restore 70 + hexio_write test.db 18 0101 71 + file exists test.db-wal 72 +} {1} 73 + 74 +do_test 2.3 { 75 + sqlite3ota ota test.db ota.db 76 + ota step 77 +} {SQLITE_ERROR} 78 + 79 +do_test 2.4 { 80 + list [catch {ota close} msg] $msg 81 +} {1 {SQLITE_ERROR - cannot update wal mode database}} 82 + 83 +#-------------------------------------------------------------------- 84 +# Test a constraint violation message with an unusual table name. 85 +# Specifically, one for which the first character is a codepoint 86 +# smaller than 30 (character '0'). 87 +# 88 +reset_db 89 +do_execsql_test 3.1 { 90 + CREATE TABLE "(t1)"(a PRIMARY KEY, b, c); 91 + INSERT INTO "(t1)" VALUES(1, 2, 3); 92 + INSERT INTO "(t1)" VALUES(4, 5, 6); 93 +} 94 +db close 95 + 96 +do_test 3.2 { 97 + forcedelete ota.db 98 + sqlite3 dbo ota.db 99 + dbo eval { 100 + CREATE TABLE "data_(t1)"(a, b, c, ota_control); 101 + INSERT INTO "data_(t1)" VALUES(4, 8, 9, 0); 102 + } 103 + dbo close 104 + 105 + sqlite3ota ota test.db ota.db 106 + ota step 107 + ota step 108 +} {SQLITE_CONSTRAINT} 109 + 110 +do_test 3.3 { 111 + list [catch {ota close} msg] $msg 112 +} {1 {SQLITE_CONSTRAINT - UNIQUE constraint failed: (t1).a}} 113 + 114 +#-------------------------------------------------------------------- 115 +# Check that once an OTA update has been applied, attempting to apply 116 +# it a second time is a no-op (as the state stored in the OTA database is 117 +# "all steps completed"). 118 +# 119 +reset_db 120 +do_execsql_test 4.1 { 121 + CREATE TABLE "(t1)"(a, b, c, PRIMARY KEY(c, b, a)); 122 + INSERT INTO "(t1)" VALUES(1, 2, 3); 123 + INSERT INTO "(t1)" VALUES(4, 5, 6); 124 +} 125 +db close 126 + 127 +do_test 4.2 { 128 + forcedelete ota.db 129 + sqlite3 dbo ota.db 130 + dbo eval { 131 + CREATE TABLE "data_(t1)"(a, b, c, ota_control); 132 + INSERT INTO "data_(t1)" VALUES(7, 8, 9, 0); 133 + INSERT INTO "data_(t1)" VALUES(1, 2, 3, 1); 134 + } 135 + dbo close 136 + 137 + sqlite3ota ota test.db ota.db 138 + while {[ota step]=="SQLITE_OK"} { } 139 + ota close 140 +} {SQLITE_DONE} 141 + 142 +do_test 4.3 { 143 + sqlite3ota ota test.db ota.db 144 + ota step 145 +} {SQLITE_DONE} 146 + 147 +do_test 4.4 { 148 + ota close 149 +} {SQLITE_DONE} 150 + 151 +do_test 4.5.1 { 152 + sqlite3 dbo ota.db 153 + dbo eval { INSERT INTO ota_state VALUES(100, 100) } 154 + dbo close 155 + sqlite3ota ota test.db ota.db 156 + ota step 157 +} {SQLITE_CORRUPT} 158 +do_test 4.5.2 { 159 + list [catch {ota close} msg] $msg 160 +} {1 SQLITE_CORRUPT} 161 +do_test 4.5.3 { 162 + sqlite3 dbo ota.db 163 + dbo eval { DELETE FROM ota_state WHERE k = 100 } 164 + dbo close 165 +} {} 166 + 167 +# Also, check that an invalid state value in the ota_state table is 168 +# detected and reported as corruption. 169 +do_test 4.6.1 { 170 + sqlite3 dbo ota.db 171 + dbo eval { UPDATE ota_state SET v = v*-1 WHERE k = 1 } 172 + dbo close 173 + sqlite3ota ota test.db ota.db 174 + ota step 175 +} {SQLITE_CORRUPT} 176 +do_test 4.6.2 { 177 + list [catch {ota close} msg] $msg 178 +} {1 SQLITE_CORRUPT} 179 +do_test 4.6.3 { 180 + sqlite3 dbo ota.db 181 + dbo eval { UPDATE ota_state SET v = v*-1 WHERE k = 1 } 182 + dbo close 183 +} {} 184 + 185 +do_test 4.7.1 { 186 + sqlite3 dbo ota.db 187 + dbo eval { UPDATE ota_state SET v = 1 WHERE k = 1 } 188 + dbo eval { UPDATE ota_state SET v = 'nosuchtable' WHERE k = 2 } 189 + dbo close 190 + sqlite3ota ota test.db ota.db 191 + ota step 192 +} {SQLITE_ERROR} 193 +do_test 4.7.2 { 194 + list [catch {ota close} msg] $msg 195 +} {1 {SQLITE_ERROR - ota_state mismatch error}} 196 + 197 +finish_test 198 +
Added ext/ota/ota12.test.
1 +# 2015 February 16 2 +# 3 +# The author disclaims copyright to this source code. In place of 4 +# a legal notice, here is a blessing: 5 +# 6 +# May you do good and not evil. 7 +# May you find forgiveness for yourself and forgive others. 8 +# May you share freely, never taking more than you give. 9 +# 10 +#*********************************************************************** 11 +# 12 + 13 +if {![info exists testdir]} { 14 + set testdir [file join [file dirname [info script]] .. .. test] 15 +} 16 +source $testdir/tester.tcl 17 +source $testdir/lock_common.tcl 18 +set ::testprefix ota12 19 + 20 +set setup_sql { 21 + DROP TABLE IF EXISTS xx; 22 + DROP TABLE IF EXISTS xy; 23 + CREATE TABLE xx(a, b, c PRIMARY KEY); 24 + INSERT INTO xx VALUES(1, 2, 3); 25 + CREATE TABLE xy(a, b, c PRIMARY KEY); 26 + 27 + ATTACH 'ota.db' AS ota; 28 + DROP TABLE IF EXISTS data_xx; 29 + CREATE TABLE ota.data_xx(a, b, c, ota_control); 30 + INSERT INTO data_xx VALUES(4, 5, 6, 0); 31 + INSERT INTO data_xx VALUES(7, 8, 9, 0); 32 + CREATE TABLE ota.data_xy(a, b, c, ota_control); 33 + INSERT INTO data_xy VALUES(10, 11, 12, 0); 34 + DETACH ota; 35 +} 36 + 37 +do_multiclient_test tn { 38 + 39 + # Initialize a target (test.db) and ota (ota.db) database. 40 + # 41 + forcedelete ota.db 42 + sql1 $setup_sql 43 + 44 + # Using connection 2, open a read transaction on the target database. 45 + # OTA will still be able to generate "test.db-oal", but it will not be 46 + # able to rename it to "test.db-wal". 47 + # 48 + do_test 1.$tn.1 { 49 + sql2 { BEGIN; SELECT * FROM xx; } 50 + } {1 2 3} 51 + do_test 1.$tn.2 { 52 + sqlite3ota ota test.db ota.db 53 + while 1 { 54 + set res [ota step] 55 + if {$res!="SQLITE_OK"} break 56 + } 57 + set res 58 + } {SQLITE_BUSY} 59 + 60 + do_test 1.$tn.3 { sql2 { SELECT * FROM xx; } } {1 2 3} 61 + do_test 1.$tn.4 { sql2 { SELECT * FROM xy; } } {} 62 + do_test 1.$tn.5 { 63 + list [file exists test.db-wal] [file exists test.db-oal] 64 + } {0 1} 65 + do_test 1.$tn.6 { sql2 COMMIT } {} 66 + 67 + # The ota object that hit the SQLITE_BUSY error above cannot be reused. 68 + # It is stuck in a permanent SQLITE_BUSY state at this point. 69 + # 70 + do_test 1.$tn.7 { ota step } {SQLITE_BUSY} 71 + do_test 1.$tn.8 { 72 + list [catch { ota close } msg] $msg 73 + } {1 SQLITE_BUSY} 74 + 75 + do_test 1.$tn.9.1 { sql2 { BEGIN EXCLUSIVE } } {} 76 + do_test 1.$tn.9.2 { 77 + sqlite3ota ota test.db ota.db 78 + ota step 79 + } {SQLITE_BUSY} 80 + do_test 1.$tn.9.3 { 81 + list [catch { ota close } msg] $msg 82 + } {1 {SQLITE_BUSY - database is locked}} 83 + do_test 1.$tn.9.4 { sql2 COMMIT } {} 84 + 85 + sqlite3ota ota test.db ota.db 86 + do_test 1.$tn.10.1 { sql2 { BEGIN EXCLUSIVE } } {} 87 + do_test 1.$tn.10.2 { 88 + ota step 89 + } {SQLITE_BUSY} 90 + do_test 1.$tn.10.3 { 91 + list [catch { ota close } msg] $msg 92 + } {1 SQLITE_BUSY} 93 + do_test 1.$tn.10.4 { sql2 COMMIT } {} 94 + 95 + # A new ota object can finish the work though. 96 + # 97 + do_test 1.$tn.11 { 98 + sqlite3ota ota test.db ota.db 99 + ota step 100 + } {SQLITE_OK} 101 + do_test 1.$tn.12 { 102 + list [file exists test.db-wal] [file exists test.db-oal] 103 + } {1 0} 104 + do_test 1.$tn.13 { 105 + while 1 { 106 + set res [ota step] 107 + if {$res!="SQLITE_OK"} break 108 + } 109 + set res 110 + } {SQLITE_DONE} 111 + 112 + do_test 1.$tn.14 { 113 + ota close 114 + } {SQLITE_DONE} 115 +} 116 + 117 +do_multiclient_test tn { 118 + 119 + # Initialize a target (test.db) and ota (ota.db) database. 120 + # 121 + forcedelete ota.db 122 + sql1 $setup_sql 123 + 124 + do_test 2.$tn.1 { 125 + sqlite3ota ota test.db ota.db 126 + while {[file exists test.db-wal]==0} { 127 + if {[ota step]!="SQLITE_OK"} {error "problem here...."} 128 + } 129 + ota close 130 + } {SQLITE_OK} 131 + 132 + 133 + do_test 2.$tn.2 { sql2 { BEGIN IMMEDIATE } } {} 134 + 135 + do_test 2.$tn.3 { 136 + sqlite3ota ota test.db ota.db 137 + ota step 138 + } {SQLITE_BUSY} 139 + 140 + do_test 2.$tn.4 { list [catch { ota close } msg] $msg } {1 SQLITE_BUSY} 141 + 142 + do_test 2.$tn.5 { 143 + sql2 { SELECT * FROM xx ; COMMIT } 144 + } {1 2 3 4 5 6 7 8 9} 145 + 146 + do_test 2.$tn.6 { 147 + sqlite3ota ota test.db ota.db 148 + ota step 149 + ota close 150 + } {SQLITE_OK} 151 + 152 + do_test 2.$tn.7 { sql2 { BEGIN EXCLUSIVE } } {} 153 + 154 + do_test 2.$tn.8 { 155 + sqlite3ota ota test.db ota.db 156 + ota step 157 + } {SQLITE_BUSY} 158 + do_test 2.$tn.9 { list [catch { ota close } msg] $msg } {1 SQLITE_BUSY} 159 + do_test 2.$tn.10 { 160 + sql2 { SELECT * FROM xx ; COMMIT } 161 + } {1 2 3 4 5 6 7 8 9} 162 + 163 + do_test 2.$tn.11 { 164 + sqlite3ota ota test.db ota.db 165 + while {[ota step]=="SQLITE_OK"} {} 166 + ota close 167 + } {SQLITE_DONE} 168 + 169 +} 170 + 171 +finish_test 172 +
Added ext/ota/ota13.test.
1 +# 2015 February 16 2 +# 3 +# The author disclaims copyright to this source code. In place of 4 +# a legal notice, here is a blessing: 5 +# 6 +# May you do good and not evil. 7 +# May you find forgiveness for yourself and forgive others. 8 +# May you share freely, never taking more than you give. 9 +# 10 +#*********************************************************************** 11 +# 12 +# Test an OTA update that features lots of different ota_control strings 13 +# for UPDATE statements. This tests OTA's internal UPDATE statement cache. 14 +# 15 + 16 +if {![info exists testdir]} { 17 + set testdir [file join [file dirname [info script]] .. .. test] 18 +} 19 +source $testdir/tester.tcl 20 +source $testdir/lock_common.tcl 21 +set ::testprefix ota13 22 + 23 +do_execsql_test 1.0 { 24 + CREATE TABLE t1(a PRIMARY KEY, b, c, d, e, f, g, h); 25 + WITH ii(i) AS (SELECT 0 UNION ALL SELECT i+1 FROM ii WHERE i<127) 26 + INSERT INTO t1 SELECT i, 0, 0, 0, 0, 0, 0, 0 FROM ii; 27 +} 28 + 29 +forcedelete ota.db 30 +do_execsql_test 1.1 { 31 + ATTACH 'ota.db' AS ota; 32 + CREATE TABLE ota.data_t1(a, b, c, d, e, f, g, h, ota_control); 33 +} 34 + 35 +do_test 1.2 { 36 + for {set i 0} {$i<128} {incr i} { 37 + set control "." 38 + for {set bit 6} {$bit>=0} {incr bit -1} { 39 + if { $i & (1<<$bit) } { 40 + append control "x" 41 + } else { 42 + append control "." 43 + } 44 + } 45 + execsql { INSERT INTO data_t1 VALUES($i, 1, 1, 1, 1, 1, 1, 1, $control) } 46 + } 47 +} {} 48 + 49 +do_test 1.3 { 50 + sqlite3ota ota test.db ota.db 51 + while 1 { 52 + set rc [ota step] 53 + if {$rc!="SQLITE_OK"} break 54 + } 55 + ota close 56 +} {SQLITE_DONE} 57 + 58 +do_execsql_test 1.4 { 59 + SELECT count(*) FROM t1 WHERE 60 + a == ( (b<<6) + (c<<5) + (d<<4) + (e<<3) + (f<<2) + (g<<1) + (h<<0) ) 61 +} {128} 62 + 63 + 64 +finish_test 65 +
Added ext/ota/ota3.test.
1 +# 2014 August 30 2 +# 3 +# The author disclaims copyright to this source code. In place of 4 +# a legal notice, here is a blessing: 5 +# 6 +# May you do good and not evil. 7 +# May you find forgiveness for yourself and forgive others. 8 +# May you share freely, never taking more than you give. 9 +# 10 +#*********************************************************************** 11 +# 12 + 13 +if {![info exists testdir]} { 14 + set testdir [file join [file dirname [info script]] .. .. test] 15 +} 16 +source $testdir/tester.tcl 17 +set ::testprefix ota3 18 + 19 + 20 +# Run the OTA in file $ota on target database $target until completion. 21 +# 22 +proc run_ota {target ota} { 23 + sqlite3ota ota $target $ota 24 + while { [ota step]=="SQLITE_OK" } {} 25 + ota close 26 +} 27 + 28 +forcedelete test.db-oal ota.db 29 +db close 30 +sqlite3_shutdown 31 +sqlite3_config_uri 1 32 +reset_db 33 + 34 +#-------------------------------------------------------------------- 35 +# Test that for an OTA to be applied, no corruption results if the 36 +# affinities on the source and target table do not match. 37 +# 38 +do_execsql_test 1.0 { 39 + CREATE TABLE x1(a INTEGER PRIMARY KEY, b TEXT, c REAL); 40 + CREATE INDEX i1 ON x1(b, c); 41 +} {} 42 + 43 +do_test 1.1 { 44 + sqlite3 db2 ota.db 45 + db2 eval { 46 + CREATE TABLE data_x1(a, b, c, ota_control); 47 + INSERT INTO data_x1 VALUES(1, '123', '123', 0); 48 + INSERT INTO data_x1 VALUES(2, 123, 123, 0); 49 + } 50 + db2 close 51 + run_ota test.db ota.db 52 +} {SQLITE_DONE} 53 + 54 +do_execsql_test 1.2 { 55 + PRAGMA integrity_check; 56 +} {ok} 57 + 58 +#-------------------------------------------------------------------- 59 +# Test that NULL values may not be inserted into INTEGER PRIMARY KEY 60 +# columns. 61 +# 62 +forcedelete ota.db 63 +reset_db 64 + 65 +do_execsql_test 2.0 { 66 + CREATE TABLE x1(a INTEGER PRIMARY KEY, b TEXT, c REAL); 67 + CREATE INDEX i1 ON x1(b, c); 68 +} {} 69 + 70 +foreach {tn otadb} { 71 + 1 { 72 + CREATE TABLE data_x1(a, b, c, ota_control); 73 + INSERT INTO data_x1 VALUES(NULL, 'a', 'b', 0); 74 + } 75 + 76 + 2 { 77 + CREATE TABLE data_x1(c, b, a, ota_control); 78 + INSERT INTO data_x1 VALUES('b', 'a', NULL, 0); 79 + } 80 +} { 81 + do_test 2.$tn.1 { 82 + forcedelete ota.db 83 + sqlite3 db2 ota.db 84 + db2 eval $otadb 85 + db2 close 86 + list [catch { run_ota test.db ota.db } msg] $msg 87 + } {1 {SQLITE_MISMATCH - datatype mismatch}} 88 + 89 + do_execsql_test 2.1.2 { 90 + PRAGMA integrity_check; 91 + } {ok} 92 +} 93 + 94 +#-------------------------------------------------------------------- 95 +# Test that missing columns are detected. 96 +# 97 +forcedelete ota.db 98 +reset_db 99 + 100 +do_execsql_test 2.0 { 101 + CREATE TABLE x1(a INTEGER PRIMARY KEY, b, c); 102 + CREATE INDEX i1 ON x1(b, c); 103 +} {} 104 + 105 +do_test 2.1 { 106 + sqlite3 db2 ota.db 107 + db2 eval { 108 + CREATE TABLE data_x1(a, b, ota_control); 109 + INSERT INTO data_x1 VALUES(1, 'a', 0); 110 + } 111 + db2 close 112 + list [catch { run_ota test.db ota.db } msg] $msg 113 +} {1 {SQLITE_ERROR - column missing from data_x1: c}} 114 + 115 +do_execsql_test 2.2 { 116 + PRAGMA integrity_check; 117 +} {ok} 118 + 119 +# Also extra columns. 120 +# 121 +do_execsql_test 2.3 { 122 + CREATE TABLE x2(a INTEGER PRIMARY KEY, b, c); 123 + CREATE INDEX i2 ON x2(b, c); 124 +} {} 125 + 126 +do_test 2.4 { 127 + forcedelete ota.db 128 + sqlite3 db2 ota.db 129 + db2 eval { 130 + CREATE TABLE data_x2(a, b, c, d, ota_control); 131 + INSERT INTO data_x2 VALUES(1, 'a', 2, 3, 0); 132 + } 133 + db2 close 134 + list [catch { run_ota test.db ota.db } msg] $msg 135 +} {1 SQLITE_ERROR} 136 + 137 +do_execsql_test 2.5 { 138 + PRAGMA integrity_check; 139 +} {ok} 140 + 141 + 142 +#------------------------------------------------------------------------- 143 +# Test that sqlite3ota_create_vfs() returns an error if the requested 144 +# parent VFS is unknown. 145 +# 146 +# And that nothing disasterous happens if a VFS name passed to 147 +# sqlite3ota_destroy_vfs() is unknown or not an OTA vfs. 148 +# 149 +do_test 3.1 { 150 + list [catch {sqlite3ota_create_vfs xyz nosuchparent} msg] $msg 151 +} {1 SQLITE_NOTFOUND} 152 + 153 +do_test 3.2 { 154 + sqlite3ota_destroy_vfs nosuchvfs 155 + sqlite3ota_destroy_vfs unix 156 + sqlite3ota_destroy_vfs win32 157 +} {} 158 + 159 +#------------------------------------------------------------------------- 160 +# Test that it is an error to specify an explicit VFS that does not 161 +# include ota VFS functionality. 162 +# 163 +do_test 4.1 { 164 + testvfs tvfs 165 + sqlite3ota ota file:test.db?vfs=tvfs ota.db 166 + list [catch { ota step } msg] $msg 167 +} {0 SQLITE_ERROR} 168 +do_test 4.2 { 169 + list [catch { ota close } msg] $msg 170 +} {1 {SQLITE_ERROR - ota vfs not found}} 171 +tvfs delete 172 + 173 +#------------------------------------------------------------------------- 174 +# Test a large ota update to ensure that wal_autocheckpoint does not get 175 +# in the way. 176 +# 177 +forcedelete ota.db 178 +reset_db 179 +do_execsql_test 5.1 { 180 + CREATE TABLE x1(a, b, c, PRIMARY KEY(a)) WITHOUT ROWID; 181 + CREATE INDEX i1 ON x1(a); 182 + 183 + ATTACH 'ota.db' AS ota; 184 + CREATE TABLE ota.data_x1(a, b, c, ota_control); 185 + WITH s(a, b, c) AS ( 186 + SELECT randomblob(300), randomblob(300), 1 187 + UNION ALL 188 + SELECT randomblob(300), randomblob(300), c+1 FROM s WHERE c<2000 189 + ) 190 + INSERT INTO data_x1 SELECT a, b, c, 0 FROM s; 191 +} 192 + 193 +do_test 5.2 { 194 + sqlite3ota ota test.db ota.db 195 + while {[ota step]=="SQLITE_OK" && [file exists test.db-wal]==0} {} 196 + ota close 197 +} {SQLITE_OK} 198 + 199 +do_test 5.3 { 200 + expr {[file size test.db-wal] > (1024 * 1200)} 201 +} 1 202 + 203 +do_test 6.1 { sqlite3ota_internal_test } {} 204 + 205 +finish_test 206 + 207 +
Added ext/ota/ota5.test.
1 +# 2014 August 30 2 +# 3 +# The author disclaims copyright to this source code. In place of 4 +# a legal notice, here is a blessing: 5 +# 6 +# May you do good and not evil. 7 +# May you find forgiveness for yourself and forgive others. 8 +# May you share freely, never taking more than you give. 9 +# 10 +#*********************************************************************** 11 +# 12 +# Test some properties of the pager_ota_mode and ota_mode pragmas. 13 +# 14 + 15 +if {![info exists testdir]} { 16 + set testdir [file join [file dirname [info script]] .. .. test] 17 +} 18 +source $testdir/tester.tcl 19 +set ::testprefix ota5 20 + 21 + 22 +# Run the OTA in file $ota on target database $target until completion. 23 +# 24 +proc run_ota {target ota} { 25 + sqlite3ota ota $target $ota 26 + while { [ota step]=="SQLITE_OK" } {} 27 + ota close 28 +} 29 + 30 + 31 +# Run the OTA in file $ota on target database $target one step at a 32 +# time until completion. 33 +# 34 +proc step_ota {target ota} { 35 + while 1 { 36 + sqlite3ota ota $target $ota 37 + set rc [ota step] 38 + ota close 39 + if {$rc != "SQLITE_OK"} break 40 + } 41 + set rc 42 +} 43 + 44 +# Return a list of the primary key columns for table $tbl in the database 45 +# opened by database handle $db. 46 +# 47 +proc pkcols {db tbl} { 48 + set ret [list] 49 + $db eval "PRAGMA table_info = '$tbl'" { 50 + if {$pk} { lappend ret $name } 51 + } 52 + return $ret 53 +} 54 + 55 +# Return a list of all columns for table $tbl in the database opened by 56 +# database handle $db. 57 +# 58 +proc allcols {db tbl} { 59 + set ret [list] 60 + $db eval "PRAGMA table_info = '$tbl'" { 61 + lappend ret $name 62 + } 63 + return $ret 64 +} 65 + 66 +# Return a checksum on all tables and data in the main database attached 67 +# to database handle $db. It is possible to add indexes without changing 68 +# the checksum. 69 +# 70 +proc datacksum {db} { 71 + 72 + $db eval { SELECT name FROM sqlite_master WHERE type='table' } { 73 + append txt $name 74 + set cols [list] 75 + set order [list] 76 + set cnt 0 77 + $db eval "PRAGMA table_info = $name" x { 78 + lappend cols "quote($x(name))" 79 + lappend order [incr cnt] 80 + } 81 + set cols [join $cols ,] 82 + set order [join $order ,] 83 + append txt [$db eval "SELECT $cols FROM $name ORDER BY $order"] 84 + } 85 + return "[string length $txt]-[md5 $txt]" 86 +} 87 + 88 +proc ucontrol {args} { 89 + set ret "" 90 + foreach a $args { 91 + if {$a} { 92 + append ret . 93 + } else { 94 + append ret x 95 + } 96 + } 97 + return $ret 98 +} 99 + 100 +# Argument $target is the name of an SQLite database file. $sql is an SQL 101 +# script containing INSERT, UPDATE and DELETE statements to execute against 102 +# it. This command creates an OTA update database in file $ota that has 103 +# the same effect as the script. The target database is not modified by 104 +# this command. 105 +# 106 +proc generate_ota_db {target ota sql} { 107 + 108 + forcedelete $ota 109 + forcecopy $target copy.db 110 + 111 + # Evaluate the SQL script to modify the contents of copy.db. 112 + # 113 + sqlite3 dbOta copy.db 114 + dbOta eval $sql 115 + 116 + dbOta function ucontrol ucontrol 117 + 118 + # Evaluate the SQL script to modify the contents of copy.db. 119 + set ret [datacksum dbOta] 120 + 121 + dbOta eval { ATTACH $ota AS ota } 122 + dbOta eval { ATTACH $target AS orig } 123 + 124 + dbOta eval { SELECT name AS tbl FROM sqlite_master WHERE type = 'table' } { 125 + set pk [pkcols dbOta $tbl] 126 + set cols [allcols dbOta $tbl] 127 + 128 + # A WHERE clause to test that the PK columns match. 129 + # 130 + set where [list] 131 + foreach c $pk { lappend where "main.$tbl.$c IS orig.$tbl.$c" } 132 + set where [join $where " AND "] 133 + 134 + # A WHERE clause to test that all columns match. 135 + # 136 + set where2 [list] 137 + foreach c $cols { lappend where2 "main.$tbl.$c IS orig.$tbl.$c" } 138 + set ucontrol "ucontrol([join $where2 ,])" 139 + set where2 [join $where2 " AND "] 140 + 141 + # Create a data_xxx table in the OTA update database. 142 + dbOta eval " 143 + CREATE TABLE ota.data_$tbl AS SELECT *, '' AS ota_control 144 + FROM main.$tbl LIMIT 0 145 + " 146 + 147 + # Find all new rows INSERTed by the script. 148 + dbOta eval " 149 + INSERT INTO ota.data_$tbl 150 + SELECT *, 0 AS ota_control FROM main.$tbl 151 + WHERE NOT EXISTS ( 152 + SELECT 1 FROM orig.$tbl WHERE $where 153 + ) 154 + " 155 + 156 + # Find all old rows DELETEd by the script. 157 + dbOta eval " 158 + INSERT INTO ota.data_$tbl 159 + SELECT *, 1 AS ota_control FROM orig.$tbl 160 + WHERE NOT EXISTS ( 161 + SELECT 1 FROM main.$tbl WHERE $where 162 + ) 163 + " 164 + 165 + # Find all rows UPDATEd by the script. 166 + set origcols [list] 167 + foreach c $cols { lappend origcols "main.$tbl.$c" } 168 + set origcols [join $origcols ,] 169 + dbOta eval " 170 + INSERT INTO ota.data_$tbl 171 + SELECT $origcols, $ucontrol AS ota_control 172 + FROM orig.$tbl, main.$tbl 173 + WHERE $where AND NOT ($where2) 174 + " 175 + 176 + } 177 + 178 + dbOta close 179 + forcedelete copy.db 180 + 181 + return $ret 182 +} 183 + 184 +#------------------------------------------------------------------------- 185 +# 186 +do_execsql_test 1.0 { 187 + CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); 188 + CREATE TABLE t2(x, y, z, PRIMARY KEY(y, z)) WITHOUT ROWID; 189 + 190 + INSERT INTO t1 VALUES(1, 2, 3); 191 + INSERT INTO t1 VALUES(2, 4, 6); 192 + INSERT INTO t1 VALUES(3, 6, 9); 193 + 194 + INSERT INTO t2 VALUES(1, 2, 3); 195 + INSERT INTO t2 VALUES(2, 4, 6); 196 + INSERT INTO t2 VALUES(3, 6, 9); 197 +} 198 +db close 199 + 200 +set cksum [generate_ota_db test.db ota.db { 201 + INSERT INTO t1 VALUES(4, 8, 12); 202 + DELETE FROM t1 WHERE a = 2; 203 + UPDATE t1 SET c = 15 WHERE a=3; 204 + 205 + INSERT INTO t2 VALUES(4, 8, 12); 206 + DELETE FROM t2 WHERE x = 2; 207 + UPDATE t2 SET x = 15 WHERE z=9; 208 +}] 209 + 210 +foreach {tn idx} { 211 + 1 { 212 + } 213 + 2 { 214 + CREATE INDEX i1 ON t1(a, b, c); 215 + CREATE INDEX i2 ON t2(x, y, z); 216 + } 217 +} { 218 + foreach cmd {run step} { 219 + forcecopy test.db test.db2 220 + forcecopy ota.db ota.db2 221 + 222 + sqlite3 db test.db2 223 + db eval $idx 224 + 225 + do_test 1.$tn.$cmd.1 { 226 + ${cmd}_ota test.db2 ota.db2 227 + datacksum db 228 + } $cksum 229 + 230 + do_test 1.$tn.$cmd.2 { 231 + db eval { PRAGMA integrity_check } 232 + } {ok} 233 + 234 + db close 235 + } 236 +} 237 + 238 +#------------------------------------------------------------------------- 239 +# 240 +reset_db 241 +do_execsql_test 2.0 { 242 + CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, d, e); 243 + INSERT INTO t1 VALUES(-750250,'fyetckfaagjkzqjx',-185831,X'FEAD',444258.29); 244 + INSERT INTO t1 VALUES(649081,NULL,X'7DF25BF78778',-342324.63,'akvspktocwozo'); 245 + INSERT INTO t1 VALUES(-133045,-44822.31,X'',287935,NULL); 246 + INSERT INTO t1 VALUES(202132,NULL,X'5399','cujsjtspryqeyovcdpz','m'); 247 + INSERT INTO t1 VALUES(302910,NULL,'dvdhivtfkaedzhdcnn',-717113.41,688487); 248 + INSERT INTO t1 VALUES(-582327,X'7A267A',X'7E6B3CFE5CB9','zacuzilrok',-196478); 249 + INSERT INTO t1 VALUES(-190462,X'D1A087E7D68D9578','lsmleti',NULL,-928094); 250 + INSERT INTO t1 VALUES(-467665,176344.57,-536684.23,828876.22,X'903E'); 251 + INSERT INTO t1 VALUES(-629138,632630.29,X'28D6',-774501,X'819BBBFC65'); 252 + INSERT INTO t1 VALUES(-828110,-54379.24,-881121.44,X'',X'8D5A894F0D'); 253 + 254 + CREATE TABLE t2(a PRIMARY KEY, b, c, d, e) WITHOUT ROWID; 255 + INSERT INTO t2 VALUES(-65174,X'AC1DBFFE27310F',-194471.08,347988,X'84041BA6F9BDDE86A8'); 256 + INSERT INTO t2 VALUES('bzbpi',-952693.69,811628.25,NULL,-817434); 257 + INSERT INTO t2 VALUES(-643830,NULL,'n',NULL,'dio'); 258 + INSERT INTO t2 VALUES('rovoenxxj',NULL,'owupbtdcoxxnvg',-119676,X'55431DFA'); 259 + INSERT INTO t2 VALUES(899770,'jlygdl',X'DBCA4D1A',NULL,-631773); 260 + INSERT INTO t2 VALUES(334698.80,NULL,-697585.58,-89277,-817352); 261 + INSERT INTO t2 VALUES(X'1A9EB7547A4AAF38','aiprdhkpzdz','anw','szvjbwdvzucybpwwqjt',X'53'); 262 + INSERT INTO t2 VALUES(713220,NULL,'hfcqhqzjuqplvkum',X'20B076075649DE','fthgpvqdyy'); 263 + INSERT INTO t2 VALUES(763908,NULL,'xgslzcpvwfknbr',X'75',X'668146'); 264 + INSERT INTO t2 VALUES(X'E1BA2B6BA27278','wjbpd',NULL,139341,-290086.15); 265 +} 266 +db close 267 + 268 +set cksum [generate_ota_db test.db ota.db { 269 +INSERT INTO t2 VALUES(222916.23,'idh',X'472C517405',X'E3',X'7C4F31824669'); 270 +INSERT INTO t2 VALUES('xcndjwafcoxwxizoktd',-319567.21,NULL,-720906.43,-577170); 271 +INSERT INTO t2 VALUES(376369.99,-536058,'yoaiurfqupdscwc',X'29EC8A2542EC3953E9',-740485.22); 272 +INSERT INTO t2 VALUES(X'0EFB4DC50693',-175590.83,X'1779E253CAB5B1789E',X'BC6903',NULL); 273 +INSERT INTO t2 VALUES(-288299,'hfrp',NULL,528477,730676.77); 274 +DELETE FROM t2 WHERE a < -60000; 275 + 276 +UPDATE t2 SET b = 'pgnnaaoflnw' WHERE a = 'bzbpi'; 277 +UPDATE t2 SET c = -675583 WHERE a = 'rovoenxxj'; 278 +UPDATE t2 SET d = X'09CDF2B2C241' WHERE a = 713220; 279 + 280 +INSERT INTO t1 VALUES(224938,'bmruycvfznhhnfmgqys','fr',854381,789143); 281 +INSERT INTO t1 VALUES(-863931,-1386.26,X'2A058540C2FB5C',NULL,X'F9D5990A'); 282 +INSERT INTO t1 VALUES(673696,X'97301F0AC5735F44B5',X'440C',227999.92,-709599.79); 283 +INSERT INTO t1 VALUES(-243640,NULL,-71718.11,X'1EEFEB38',X'8CC7C55D95E142FBA5'); 284 +INSERT INTO t1 VALUES(275893,X'',375606.30,X'0AF9EC334711FB',-468194); 285 +DELETE FROM t1 WHERE a > 200000; 286 + 287 +UPDATE t1 SET b = 'pgnnaaoflnw' WHERE a = -190462; 288 +UPDATE t1 SET c = -675583 WHERE a = -467665; 289 +UPDATE t1 SET d = X'09CDF2B2C241' WHERE a = -133045; 290 + 291 +}] 292 + 293 +foreach {tn idx} { 294 + 1 { 295 + } 296 + 2 { 297 + CREATE UNIQUE INDEX i1 ON t1(b, c, d); 298 + CREATE UNIQUE INDEX i2 ON t1(d, e, a); 299 + CREATE UNIQUE INDEX i3 ON t1(e, d, c, b); 300 + 301 + CREATE UNIQUE INDEX i4 ON t2(b, c, d); 302 + CREATE UNIQUE INDEX i5 ON t2(d, e, a); 303 + CREATE UNIQUE INDEX i6 ON t2(e, d, c, b); 304 + } 305 +} { 306 + foreach cmd {run step} { 307 + forcecopy test.db test.db2 308 + forcecopy ota.db ota.db2 309 + 310 + sqlite3 db test.db2 311 + db eval $idx 312 + 313 + do_test 2.$tn.$cmd.1 { 314 + ${cmd}_ota test.db2 ota.db2 315 + datacksum db 316 + } $cksum 317 + 318 + do_test 2.$tn.$cmd.2 { 319 + db eval { PRAGMA integrity_check } 320 + } {ok} 321 + 322 + db close 323 + } 324 +} 325 + 326 + 327 +finish_test 328 + 329 + 330 + 331 +
Added ext/ota/ota6.test.
1 +# 2014 October 21 2 +# 3 +# The author disclaims copyright to this source code. In place of 4 +# a legal notice, here is a blessing: 5 +# 6 +# May you do good and not evil. 7 +# May you find forgiveness for yourself and forgive others. 8 +# May you share freely, never taking more than you give. 9 +# 10 +#*********************************************************************** 11 +# 12 +# This file contains tests for the OTA module. Specifically, it tests the 13 +# outcome of some other client writing to the database while an OTA update 14 +# is being applied. 15 + 16 +if {![info exists testdir]} { 17 + set testdir [file join [file dirname [info script]] .. .. test] 18 +} 19 +source $testdir/tester.tcl 20 +set ::testprefix ota6 21 + 22 +proc setup_test {} { 23 + reset_db 24 + execsql { 25 + CREATE TABLE t1(a INTEGER PRIMARY KEY, b UNIQUE); 26 + CREATE TABLE t2(a INTEGER PRIMARY KEY, b UNIQUE); 27 + CREATE TABLE t3(a INTEGER PRIMARY KEY, b UNIQUE); 28 + } 29 + db close 30 + 31 + forcedelete ota.db 32 + sqlite3 ota ota.db 33 + ota eval { 34 + CREATE TABLE data_t1(a, b, ota_control); 35 + CREATE TABLE data_t2(a, b, ota_control); 36 + CREATE TABLE data_t3(a, b, ota_control); 37 + INSERT INTO data_t1 VALUES(1, 't1', 0); 38 + INSERT INTO data_t2 VALUES(2, 't2', 0); 39 + INSERT INTO data_t3 VALUES(3, 't3', 0); 40 + } 41 + ota close 42 +} 43 + 44 +# Test the outcome of some other client writing the db while the *-oal 45 +# file is being generated. Once this has happened, the update cannot be 46 +# progressed. 47 +# 48 +for {set nStep 1} {$nStep < 8} {incr nStep} { 49 + do_test 1.$nStep.1 { 50 + setup_test 51 + sqlite3ota ota test.db ota.db 52 + for {set i 0} {$i<$nStep} {incr i} {ota step} 53 + 54 + ota close 55 + sqlite3 db test.db 56 + execsql { INSERT INTO t1 VALUES(5, 'hello') } 57 + sqlite3ota ota test.db ota.db 58 + ota step 59 + } {SQLITE_BUSY} 60 + do_test 1.$nStep.2 { 61 + ota step 62 + } {SQLITE_BUSY} 63 + do_test 1.$nStep.3 { 64 + list [file exists test.db-oal] [file exists test.db-wal] 65 + } {1 0} 66 + do_test 1.$nStep.4 { 67 + list [catch { ota close } msg] $msg 68 + } {1 {SQLITE_BUSY - database modified during ota update}} 69 +} 70 + 71 +# Test the outcome of some other client writing the db after the *-oal 72 +# file has been copied to the *-wal path. Once this has happened, any 73 +# other client writing to the db causes OTA to consider its job finished. 74 +# 75 +for {set nStep 8} {$nStep < 20} {incr nStep} { 76 + do_test 1.$nStep.1 { 77 + setup_test 78 + sqlite3ota ota test.db ota.db 79 + for {set i 0} {$i<$nStep} {incr i} {ota step} 80 + ota close 81 + sqlite3 db test.db 82 + execsql { INSERT INTO t1 VALUES(5, 'hello') } 83 + sqlite3ota ota test.db ota.db 84 + ota step 85 + } {SQLITE_DONE} 86 + do_test 1.$nStep.2 { 87 + ota step 88 + } {SQLITE_DONE} 89 + do_test 1.$nStep.3 { 90 + file exists test.db-oal 91 + } {0} 92 + do_test 1.$nStep.4 { 93 + list [catch { ota close } msg] $msg 94 + } {0 SQLITE_DONE} 95 + 96 + do_execsql_test 1.$nStep.5 { 97 + SELECT * FROM t1; 98 + } {1 t1 5 hello} 99 +} 100 + 101 + 102 +finish_test 103 +
Added ext/ota/ota7.test.
1 +# 2014 October 21 2 +# 3 +# The author disclaims copyright to this source code. In place of 4 +# a legal notice, here is a blessing: 5 +# 6 +# May you do good and not evil. 7 +# May you find forgiveness for yourself and forgive others. 8 +# May you share freely, never taking more than you give. 9 +# 10 +#*********************************************************************** 11 +# 12 +# This file contains tests for the OTA module. 13 +# 14 + 15 + 16 +if {![info exists testdir]} { 17 + set testdir [file join [file dirname [info script]] .. .. test] 18 +} 19 +source $testdir/tester.tcl 20 +set ::testprefix ota7 21 + 22 +# Test index: 23 +# 24 +# 1.*: That affinities are correctly applied to values within the 25 +# OTA database. 26 +# 27 +# 2.*: Tests for multi-column primary keys. 28 +# 29 + 30 +do_test 1.0 { 31 + execsql { 32 + CREATE TABLE t1(a INT PRIMARY KEY, b) WITHOUT ROWID; 33 + INSERT INTO t1 VALUES(1, 'abc'); 34 + INSERT INTO t1 VALUES(2, 'def'); 35 + } 36 + 37 + forcedelete ota.db 38 + sqlite3 ota ota.db 39 + ota eval { 40 + CREATE TABLE data_t1(a, b, ota_control); 41 + INSERT INTO data_t1 VALUES('1', NULL, 1); 42 + } 43 + ota close 44 +} {} 45 + 46 +do_test 1.1 { 47 + sqlite3ota ota test.db ota.db 48 + while { [ota step]=="SQLITE_OK" } {} 49 + ota close 50 +} {SQLITE_DONE} 51 + 52 +sqlite3 db test.db 53 +do_execsql_test 1.2 { 54 + SELECT * FROM t1 55 +} {2 def} 56 + 57 +#------------------------------------------------------------------------- 58 +# 59 +foreach {tn tbl} { 60 + 1 { CREATE TABLE t1(a, b, c, PRIMARY KEY(a, b)) WITHOUT ROWID } 61 + 2 { CREATE TABLE t1(a, b, c, PRIMARY KEY(a, b)) } 62 +} { 63 + reset_db 64 + 65 + execsql $tbl 66 + do_execsql_test 2.$tn.1 { 67 + CREATE INDEX t1c ON t1(c); 68 + INSERT INTO t1 VALUES(1, 1, 'a'); 69 + INSERT INTO t1 VALUES(1, 2, 'b'); 70 + INSERT INTO t1 VALUES(2, 1, 'c'); 71 + INSERT INTO t1 VALUES(2, 2, 'd'); 72 + } 73 + 74 + do_test 2.$tn.2 { 75 + forcedelete ota.db 76 + sqlite3 ota ota.db 77 + execsql { 78 + CREATE TABLE data_t1(a, b, c, ota_control); 79 + INSERT INTO data_t1 VALUES(3, 1, 'e', 0); 80 + INSERT INTO data_t1 VALUES(3, 2, 'f', 0); 81 + INSERT INTO data_t1 VALUES(1, 2, NULL, 1); 82 + INSERT INTO data_t1 VALUES(2, 1, 'X', '..x'); 83 + } ota 84 + ota close 85 + } {} 86 + 87 + do_test 2.$tn.3 { 88 + set rc "SQLITE_OK" 89 + while {$rc == "SQLITE_OK"} { 90 + sqlite3ota ota test.db ota.db 91 + ota step 92 + set rc [ota close] 93 + } 94 + set rc 95 + } {SQLITE_DONE} 96 + 97 + do_execsql_test 2.$tn.1 { 98 + SELECT * FROM t1 ORDER BY a, b 99 + } { 100 + 1 1 a 101 + 2 1 X 102 + 2 2 d 103 + 3 1 e 104 + 3 2 f 105 + } 106 +} 107 + 108 +finish_test 109 + 110 +
Added ext/ota/ota8.test.
1 +# 2014 November 20 2 +# 3 +# The author disclaims copyright to this source code. In place of 4 +# a legal notice, here is a blessing: 5 +# 6 +# May you do good and not evil. 7 +# May you find forgiveness for yourself and forgive others. 8 +# May you share freely, never taking more than you give. 9 +# 10 +#*********************************************************************** 11 +# 12 +# Test the ota_delta() feature. 13 +# 14 + 15 +if {![info exists testdir]} { 16 + set testdir [file join [file dirname [info script]] .. .. test] 17 +} 18 +source $testdir/tester.tcl 19 +set ::testprefix ota8 20 + 21 +do_execsql_test 1.0 { 22 + CREATE TABLE t1(x, y PRIMARY KEY, z); 23 + INSERT INTO t1 VALUES(NULL, 1, 'one'); 24 + INSERT INTO t1 VALUES(NULL, 2, 'two'); 25 + INSERT INTO t1 VALUES(NULL, 3, 'three'); 26 + CREATE INDEX i1z ON t1(z, x); 27 +} 28 + 29 +do_test 1.1 { 30 + forcedelete ota.db 31 + sqlite3 db2 ota.db 32 + db2 eval { 33 + CREATE TABLE data_t1(x, y, z, ota_control); 34 + INSERT INTO data_t1 VALUES('a', 1, '_i' , 'x.d'); 35 + INSERT INTO data_t1 VALUES('b', 2, 2 , '..x'); 36 + INSERT INTO data_t1 VALUES('_iii', 3, '-III' , 'd.d'); 37 + } 38 + db2 close 39 +} {} 40 + 41 +do_test 1.2.1 { 42 + sqlite3ota ota test.db ota.db 43 + ota step 44 +} {SQLITE_ERROR} 45 +do_test 1.2.2 { 46 + list [catch {ota close} msg] $msg 47 +} {1 {SQLITE_ERROR - no such function: ota_delta}} 48 + 49 +proc ota_delta {orig new} { 50 + return "${orig}${new}" 51 +} 52 + 53 +do_test 1.3.1 { 54 + while 1 { 55 + sqlite3ota ota test.db ota.db 56 + ota create_ota_delta 57 + set rc [ota step] 58 + if {$rc != "SQLITE_OK"} break 59 + ota close 60 + } 61 + ota close 62 +} {SQLITE_DONE} 63 + 64 +do_execsql_test 1.3.2 { 65 + SELECT * FROM t1 66 +} { 67 + a 1 one_i 68 + {} 2 2 69 + _iii 3 three-III 70 +} 71 +integrity_check 1.3.3 72 + 73 + 74 +finish_test 75 +
Added ext/ota/ota9.test.
1 +# 2014 November 21 2 +# 3 +# The author disclaims copyright to this source code. In place of 4 +# a legal notice, here is a blessing: 5 +# 6 +# May you do good and not evil. 7 +# May you find forgiveness for yourself and forgive others. 8 +# May you share freely, never taking more than you give. 9 +# 10 +#*********************************************************************** 11 +# 12 +# Test OTA with virtual tables. And tables with no PRIMARY KEY declarations. 13 +# 14 + 15 +if {![info exists testdir]} { 16 + set testdir [file join [file dirname [info script]] .. .. test] 17 +} 18 +source $testdir/tester.tcl 19 +set ::testprefix ota9 20 + 21 +ifcapable !fts3 { 22 + finish_test 23 + return 24 +} 25 + 26 +do_execsql_test 1.1 { 27 + CREATE VIRTUAL TABLE f1 USING fts4(a, b, c); 28 + INSERT INTO f1(rowid, a, b, c) VALUES(11, 'a', 'b', 'c'); 29 + INSERT INTO f1(rowid, a, b, c) VALUES(12, 'd', 'e', 'f'); 30 + INSERT INTO f1(rowid, a, b, c) VALUES(13, 'g', 'h', 'i'); 31 +} 32 + 33 +do_test 1.1 { 34 + forcedelete ota.db 35 + sqlite3 db2 ota.db 36 + db2 eval { 37 + CREATE TABLE data_f1(ota_rowid, a, b, c, ota_control); 38 + INSERT INTO data_f1 VALUES(14, 'x', 'y', 'z', 0); -- INSERT 39 + INSERT INTO data_f1 VALUES(11, NULL, NULL, NULL, 1); -- DELETE 40 + INSERT INTO data_f1 VALUES(13, NULL, NULL, 'X', '..x'); -- UPDATE 41 + } 42 + db2 close 43 +} {} 44 + 45 +do_test 1.2.1 { 46 + while 1 { 47 + sqlite3ota ota test.db ota.db 48 + set rc [ota step] 49 + if {$rc != "SQLITE_OK"} break 50 + ota close 51 + } 52 + ota close 53 +} {SQLITE_DONE} 54 + 55 +do_execsql_test 1.2.2 { SELECT rowid, * FROM f1 } { 56 + 12 d e f 57 + 13 g h X 58 + 14 x y z 59 +} 60 +do_execsql_test 1.2.3 { INSERT INTO f1(f1) VALUES('integrity-check') } 61 +integrity_check 1.2.4 62 + 63 +#------------------------------------------------------------------------- 64 +# Tables with no PK declaration. 65 +# 66 + 67 +# Run the OTA in file $ota on target database $target until completion. 68 +# 69 +proc run_ota {target ota} { 70 + sqlite3ota ota $target $ota 71 + while { [ota step]=="SQLITE_OK" } {} 72 + ota close 73 +} 74 + 75 +foreach {tn idx} { 76 + 1 { } 77 + 2 { 78 + CREATE INDEX i1 ON t1(a); 79 + } 80 + 3 { 81 + CREATE INDEX i1 ON t1(b, c); 82 + CREATE INDEX i2 ON t1(c, b); 83 + CREATE INDEX i3 ON t1(a, a, a, b, b, b, c, c, c); 84 + } 85 +} { 86 + 87 + reset_db 88 + do_execsql_test 2.$tn.1 { 89 + CREATE TABLE t1(a, b, c); 90 + INSERT INTO t1 VALUES(1, 2, 3); 91 + INSERT INTO t1 VALUES(4, 5, 6); 92 + INSERT INTO t1(rowid, a, b, c) VALUES(-1, 'a', 'b', 'c'); 93 + INSERT INTO t1(rowid, a, b, c) VALUES(-2, 'd', 'e', 'f'); 94 + } 95 + 96 + db eval $idx 97 + 98 + do_test 2.$tn.2 { 99 + forcedelete ota.db 100 + sqlite3 db2 ota.db 101 + db2 eval { 102 + CREATE TABLE data_t1(ota_rowid, a, b, c, ota_control); 103 + INSERT INTO data_t1 VALUES(3, 'x', 'y', 'z', 0); 104 + INSERT INTO data_t1 VALUES(NULL, 'X', 'Y', 'Z', 0); 105 + INSERT INTO data_t1 VALUES('1', NULL, NULL, NULL, 1); 106 + INSERT INTO data_t1 VALUES(-2, NULL, NULL, 'fff', '..x'); 107 + } 108 + db2 close 109 + } {} 110 + 111 + run_ota test.db ota.db 112 + 113 + do_execsql_test 2.$tn.3 { 114 + SELECT rowid, a, b, c FROM t1 ORDER BY rowid; 115 + } { 116 + -2 d e fff 117 + -1 a b c 118 + 2 4 5 6 119 + 3 x y z 120 + 4 X Y Z 121 + } 122 + 123 + integrity_check 2.$tn.4 124 +} 125 + 126 + 127 +finish_test 128 +
Added ext/ota/otaA.test.
1 +# 2014 August 30 2 +# 3 +# The author disclaims copyright to this source code. In place of 4 +# a legal notice, here is a blessing: 5 +# 6 +# May you do good and not evil. 7 +# May you find forgiveness for yourself and forgive others. 8 +# May you share freely, never taking more than you give. 9 +# 10 +#*********************************************************************** 11 +# 12 +# This file contains tests for the OTA module. More specifically, it 13 +# contains tests to ensure that it is an error to attempt to update 14 +# a wal mode database via OTA. 15 +# 16 + 17 +if {![info exists testdir]} { 18 + set testdir [file join [file dirname [info script]] .. .. test] 19 +} 20 +source $testdir/tester.tcl 21 +set ::testprefix otaA 22 + 23 +set db_sql { 24 + CREATE TABLE t1(a PRIMARY KEY, b, c); 25 +} 26 +set ota_sql { 27 + CREATE TABLE data_t1(a, b, c, ota_control); 28 + INSERT INTO data_t1 VALUES(1, 2, 3, 0); 29 + INSERT INTO data_t1 VALUES(4, 5, 6, 0); 30 + INSERT INTO data_t1 VALUES(7, 8, 9, 0); 31 +} 32 + 33 +do_test 1.0 { 34 + db close 35 + forcedelete test.db ota.db 36 + 37 + sqlite3 db test.db 38 + db eval $db_sql 39 + db eval { PRAGMA journal_mode = wal } 40 + db close 41 + 42 + sqlite3 db ota.db 43 + db eval $ota_sql 44 + db close 45 + 46 + sqlite3ota ota test.db ota.db 47 + ota step 48 +} {SQLITE_ERROR} 49 +do_test 1.1 { 50 + list [catch { ota close } msg] $msg 51 +} {1 {SQLITE_ERROR - cannot update wal mode database}} 52 + 53 +do_test 2.0 { 54 + forcedelete test.db ota.db 55 + 56 + sqlite3 db test.db 57 + db eval $db_sql 58 + db close 59 + 60 + sqlite3 db ota.db 61 + db eval $ota_sql 62 + db close 63 + 64 + sqlite3ota ota test.db ota.db 65 + ota step 66 + ota close 67 +} {SQLITE_OK} 68 + 69 +do_test 2.1 { 70 + sqlite3 db test.db 71 + db eval {PRAGMA journal_mode = wal} 72 + db close 73 + breakpoint 74 + sqlite3ota ota test.db ota.db 75 + ota step 76 +} {SQLITE_ERROR} 77 + 78 +do_test 2.2 { 79 + list [catch { ota close } msg] $msg 80 +} {1 {SQLITE_ERROR - cannot update wal mode database}} 81 + 82 + 83 +finish_test 84 +
Added ext/ota/otacrash.test.
1 +# 2014 October 22 2 +# 3 +# The author disclaims copyright to this source code. In place of 4 +# a legal notice, here is a blessing: 5 +# 6 +# May you do good and not evil. 7 +# May you find forgiveness for yourself and forgive others. 8 +# May you share freely, never taking more than you give. 9 +# 10 +#*********************************************************************** 11 +# 12 + 13 +if {![info exists testdir]} { 14 + set testdir [file join [file dirname [info script]] .. .. test] 15 +} 16 +source $testdir/tester.tcl 17 +set ::testprefix otacrash 18 + 19 +db close 20 +forcedelete test.db-oal ota.db 21 +sqlite3_shutdown 22 +sqlite3_config_uri 1 23 +reset_db 24 + 25 +# Set up a target database and an ota update database. The target 26 +# db is the usual "test.db", the ota db is "test.db2". 27 +# 28 +forcedelete test.db2 29 +do_execsql_test 1.0 { 30 + CREATE TABLE t1(a, b, c, PRIMARY KEY(a), UNIQUE(b)); 31 + INSERT INTO t1 VALUES(1, 2, 3); 32 + INSERT INTO t1 VALUES(4, 5, 6); 33 + INSERT INTO t1 VALUES(7, 8, 9); 34 + 35 + ATTACH 'test.db2' AS ota; 36 + CREATE TABLE ota.data_t1(a, b, c, ota_control); 37 + INSERT INTO data_t1 VALUES(10, 11, 12, 0); 38 + INSERT INTO data_t1 VALUES(13, 14, 15, 0); 39 + INSERT INTO data_t1 VALUES(4, NULL, NULL, 1); 40 + INSERT INTO data_t1 VALUES(1, NULL, 100, '..x'); 41 +} 42 +db_save_and_close 43 + 44 + 45 +# Determine the number of steps in applying the ota update to the test 46 +# target database created above. Set $::ota_num_steps accordingly 47 +# 48 +# Check that the same number of steps are required to apply the ota 49 +# update using many calls to sqlite3ota_step() on a single ota handle 50 +# as required to apply it using a series of ota handles, on each of 51 +# which sqlite3ota_step() is called once. 52 +# 53 +do_test 1.1 { 54 + db_restore 55 + sqlite3ota ota test.db test.db2 56 + breakpoint 57 + set nStep 0 58 + while {[ota step]=="SQLITE_OK"} { incr nStep } 59 + ota close 60 +} {SQLITE_DONE} 61 +set ota_num_steps $nStep 62 +do_test 1.2 { 63 + db_restore 64 + set nStep 0 65 + while {1} { 66 + sqlite3ota ota test.db test.db2 67 + ota step 68 + if {[ota close]=="SQLITE_DONE"} break 69 + incr nStep 70 + } 71 + set nStep 72 +} $ota_num_steps 73 + 74 + 75 +# Run one or more tests using the target (test.db) and ota (test.db2) 76 +# databases created above. As follows: 77 +# 78 +# 1. This process starts the ota update and calls sqlite3ota_step() 79 +# $nPre times. Then closes the ota update handle. 80 +# 81 +# 2. A second process resumes the ota update and attempts to call 82 +# sqlite3ota_step() $nStep times before closing the handle. A 83 +# crash is simulated during each xSync() of file test.db2. 84 +# 85 +# 3. This process attempts to resume the ota update from whatever 86 +# state it was left in by step (2). Test that it is successful 87 +# in doing so and that the final target database is as expected. 88 +# 89 +# In total (nSync+1) tests are run, where nSync is the number of times 90 +# xSync() is called on test.db2. 91 +# 92 +proc do_ota_crash_test {tn nPre nStep} { 93 + 94 + set script [subst -nocommands { 95 + sqlite3ota ota test.db file:test.db2?vfs=crash 96 + set i 0 97 + while {[set i] < $nStep} { 98 + if {[ota step]!="SQLITE_OK"} break 99 + incr i 100 + } 101 + ota close 102 + }] 103 + 104 + set bDone 0 105 + for {set iDelay 1} {$bDone==0} {incr iDelay} { 106 + forcedelete test.db2 test.db2-journal test.db test.db-oal test.db-wal 107 + db_restore 108 + 109 + if {$nPre>0} { 110 + sqlite3ota ota test.db file:test.db2 111 + set i 0 112 + for {set i 0} {$i < $nPre} {incr i} { 113 + if {[ota step]!="SQLITE_OK"} break 114 + } 115 + ota close 116 + } 117 + 118 + set res [ 119 + crashsql -file test.db2 -delay $iDelay -tclbody $script -opendb {} {} 120 + ] 121 + 122 + set bDone 1 123 + if {$res == "1 {child process exited abnormally}"} { 124 + set bDone 0 125 + } elseif {$res != "0 {}"} { 126 + error "unexected catchsql result: $res" 127 + } 128 + 129 + sqlite3ota ota test.db test.db2 130 + while {[ota step]=="SQLITE_OK"} {} 131 + ota close 132 + 133 + sqlite3 db test.db 134 + do_execsql_test $tn.delay=$iDelay { 135 + SELECT * FROM t1; 136 + PRAGMA integrity_check; 137 + } {1 2 100 7 8 9 10 11 12 13 14 15 ok} 138 + db close 139 + } 140 +} 141 + 142 +for {set nPre 0} {$nPre < $ota_num_steps} {incr nPre} { 143 + for {set is 1} {$is <= ($ota_num_steps - $nPre)} {incr is} { 144 + do_ota_crash_test 2.pre=$nPre.step=$is $nPre $is 145 + } 146 +} 147 + 148 +finish_test 149 +
Added ext/ota/otafault.test.
1 +# 2014 October 22 2 +# 3 +# The author disclaims copyright to this source code. In place of 4 +# a legal notice, here is a blessing: 5 +# 6 +# May you do good and not evil. 7 +# May you find forgiveness for yourself and forgive others. 8 +# May you share freely, never taking more than you give. 9 +# 10 +#*********************************************************************** 11 +# 12 + 13 +if {![info exists testdir]} { 14 + set testdir [file join [file dirname [info script]] .. .. test] 15 +} 16 +source $testdir/tester.tcl 17 +source $testdir/malloc_common.tcl 18 +set ::testprefix otafault 19 + 20 +proc copy_if_exists {src target} { 21 + if {[file exists $src]} { 22 + forcecopy $src $target 23 + } else { 24 + forcedelete $target 25 + } 26 +} 27 + 28 +foreach {tn2 setup sql expect} { 29 + 1 { 30 + CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); 31 + CREATE INDEX t1cb ON t1(c, b); 32 + INSERT INTO t1 VALUES(1, 1, 1); 33 + INSERT INTO t1 VALUES(2, 2, 2); 34 + INSERT INTO t1 VALUES(3, 3, 3); 35 + 36 + CREATE TABLE ota.data_t1(a, b, c, ota_control); 37 + INSERT INTO data_t1 VALUES(2, NULL, NULL, 1); 38 + INSERT INTO data_t1 VALUES(3, 'three', NULL, '.x.'); 39 + INSERT INTO data_t1 VALUES(4, 4, 4, 0); 40 + } { 41 + SELECT * FROM t1 42 + } {1 1 1 3 three 3 4 4 4} 43 + 44 + 2 { 45 + CREATE TABLE t2(a PRIMARY KEY, b, c) WITHOUT ROWID; 46 + CREATE INDEX t2cb ON t2(c, b); 47 + INSERT INTO t2 VALUES('a', 'a', 'a'); 48 + INSERT INTO t2 VALUES('b', 'b', 'b'); 49 + INSERT INTO t2 VALUES('c', 'c', 'c'); 50 + 51 + CREATE TABLE ota.data_t2(a, b, c, ota_control); 52 + INSERT INTO data_t2 VALUES('b', NULL, NULL, 1); 53 + INSERT INTO data_t2 VALUES('c', 'see', NULL, '.x.'); 54 + INSERT INTO data_t2 VALUES('d', 'd', 'd', 0); 55 + } { 56 + SELECT * FROM t2 57 + } {a a a c see c d d d} 58 + 59 + 3 { 60 + CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); 61 + CREATE TABLE t2(a PRIMARY KEY, b, c) WITHOUT ROWID; 62 + CREATE INDEX t1cb ON t1(c, b); 63 + CREATE INDEX t2cb ON t2(c, b); 64 + 65 + CREATE TABLE ota.data_t1(a, b, c, ota_control); 66 + CREATE TABLE ota.data_t2(a, b, c, ota_control); 67 + INSERT INTO data_t1 VALUES(1, 2, 3, 0); 68 + INSERT INTO data_t2 VALUES(4, 5, 6, 0); 69 + } { 70 + SELECT * FROM t1 UNION ALL SELECT * FROM t2 71 + } {1 2 3 4 5 6} 72 + 73 + 4 { 74 + CREATE TABLE t1(a PRIMARY KEY, b, c); 75 + CREATE INDEX t1c ON t1(c); 76 + INSERT INTO t1 VALUES('A', 'B', 'C'); 77 + INSERT INTO t1 VALUES('D', 'E', 'F'); 78 + 79 + CREATE TABLE ota.data_t1(a, b, c, ota_control); 80 + INSERT INTO data_t1 VALUES('D', NULL, NULL, 1); 81 + INSERT INTO data_t1 VALUES('A', 'Z', NULL, '.x.'); 82 + INSERT INTO data_t1 VALUES('G', 'H', 'I', 0); 83 + } { 84 + SELECT * FROM t1 ORDER BY a; 85 + } {A Z C G H I} 86 + 87 + 5 { 88 + CREATE TABLE t1(a, b, c); 89 + CREATE INDEX t1c ON t1(c, b); 90 + 91 + CREATE TABLE ota.data_t1(a, b, c, ota_rowid, ota_control); 92 + INSERT INTO data_t1 VALUES('a', 'b', 'c', 1, 0); 93 + INSERT INTO data_t1 VALUES('d', 'e', 'f', '2', 0); 94 + } { 95 + SELECT * FROM t1 ORDER BY a; 96 + } {a b c d e f} 97 + 98 +} { 99 + catch {db close} 100 + forcedelete ota.db test.db 101 + sqlite3 db test.db 102 + execsql { 103 + PRAGMA encoding = utf16; 104 + ATTACH 'ota.db' AS ota; 105 + } 106 + execsql $setup 107 + db close 108 + 109 + forcecopy test.db test.db.bak 110 + forcecopy ota.db ota.db.bak 111 + 112 + foreach {tn f reslist} { 113 + 1 oom-tra* { 114 + {0 SQLITE_DONE} 115 + {1 {SQLITE_NOMEM - out of memory}} 116 + {1 SQLITE_NOMEM} 117 + {1 SQLITE_IOERR_NOMEM} 118 + {1 {SQLITE_NOMEM - unable to open a temporary database file for storing temporary tables}} 119 + } 120 + 121 + 2 ioerr-* { 122 + {0 SQLITE_DONE} 123 + {1 {SQLITE_IOERR - disk I/O error}} 124 + {1 SQLITE_IOERR} 125 + {1 SQLITE_IOERR_WRITE} 126 + {1 SQLITE_IOERR_READ} 127 + {1 SQLITE_IOERR_FSYNC} 128 + {1 {SQLITE_ERROR - SQL logic error or missing database}} 129 + {1 {SQLITE_ERROR - unable to open database: ota.db}} 130 + {1 {SQLITE_IOERR - unable to open database: ota.db}} 131 + } 132 + 133 + 3 shmerr-* { 134 + {0 SQLITE_DONE} 135 + {1 {SQLITE_IOERR - disk I/O error}} 136 + {1 SQLITE_IOERR} 137 + } 138 + } { 139 + 140 + catch {db close} 141 + sqlite3_shutdown 142 + set lookaside_config [sqlite3_config_lookaside 0 0] 143 + sqlite3_initialize 144 + autoinstall_test_functions 145 + 146 + do_faultsim_test 2.$tn2 -faults $::f -prep { 147 + catch { db close } 148 + forcedelete test.db-journal test.db-wal ota.db-journal ota.db-wal 149 + forcecopy test.db.bak test.db 150 + forcecopy ota.db.bak ota.db 151 + } -body { 152 + sqlite3ota ota test.db ota.db 153 + while {[ota step]=="SQLITE_OK"} {} 154 + ota close 155 + } -test { 156 + faultsim_test_result {*}$::reslist 157 + if {$testrc==0} { 158 + sqlite3 db test.db 159 + faultsim_integrity_check 160 + set res [db eval $::sql] 161 + if {$res != [list {*}$::expect]} { 162 + puts "" 163 + puts "res: $res" 164 + puts "exp: $expect" 165 + error "data not as expected!" 166 + } 167 + } 168 + } 169 + 170 + catch {db close} 171 + sqlite3_shutdown 172 + sqlite3_config_lookaside {*}$lookaside_config 173 + sqlite3_initialize 174 + autoinstall_test_functions 175 + 176 + 177 + for {set iStep 0} {$iStep<=21} {incr iStep} { 178 + 179 + forcedelete test.db-journal test.db-wal ota.db-journal ota.db-wal 180 + 181 + copy_if_exists test.db.bak test.db 182 + copy_if_exists ota.db.bak ota.db 183 + 184 + sqlite3ota ota test.db ota.db 185 + for {set x 0} {$x < $::iStep} {incr x} { ota step } 186 + ota close 187 + 188 +# sqlite3 x ota.db ; puts "XYZ [x eval { SELECT * FROM ota_state } ]" ; x close 189 + 190 + copy_if_exists test.db test.db.bak.2 191 + copy_if_exists test.db-wal test.db.bak.2-wal 192 + copy_if_exists test.db-oal test.db.bak.2-oal 193 + copy_if_exists ota.db ota.db.bak.2 194 + 195 + do_faultsim_test 3.$tn.$iStep -faults $::f -prep { 196 + catch { db close } 197 + forcedelete test.db-journal test.db-wal ota.db-journal ota.db-wal 198 + copy_if_exists test.db.bak.2 test.db 199 + copy_if_exists test.db.bak.2-wal test.db-wal 200 + copy_if_exists test.db.bak.2-oal test.db-oal 201 + copy_if_exists ota.db.bak.2 ota.db 202 + } -body { 203 + sqlite3ota ota test.db ota.db 204 + ota step 205 + ota close 206 + } -test { 207 + 208 + if {$testresult=="SQLITE_OK"} {set testresult "SQLITE_DONE"} 209 + faultsim_test_result {*}$::reslist 210 + 211 + if {$testrc==0} { 212 + # No error occurred. If the OTA has not already been fully applied, 213 + # apply the rest of it now. Then ensure that the final state of the 214 + # target db is as expected. And that "PRAGMA integrity_check" 215 + # passes. 216 + sqlite3ota ota test.db ota.db 217 + while {[ota step] == "SQLITE_OK"} {} 218 + ota close 219 + 220 + sqlite3 db test.db 221 + faultsim_integrity_check 222 + 223 + set res [db eval $::sql] 224 + if {$res != [list {*}$::expect]} { 225 + puts "" 226 + puts "res: $res" 227 + puts "exp: $::expect" 228 + error "data not as expected!" 229 + } 230 + } 231 + } 232 + } 233 + } 234 +} 235 + 236 +finish_test 237 +
Added ext/ota/otafault2.test.
1 +# 2014 October 22 2 +# 3 +# The author disclaims copyright to this source code. In place of 4 +# a legal notice, here is a blessing: 5 +# 6 +# May you do good and not evil. 7 +# May you find forgiveness for yourself and forgive others. 8 +# May you share freely, never taking more than you give. 9 +# 10 +#*********************************************************************** 11 +# 12 + 13 +if {![info exists testdir]} { 14 + set testdir [file join [file dirname [info script]] .. .. test] 15 +} 16 +source $testdir/tester.tcl 17 +source $testdir/malloc_common.tcl 18 +set ::testprefix otafault2 19 + 20 +forcedelete ota.db 21 +do_execsql_test 1.0 { 22 + CREATE TABLE target(x UNIQUE, y, z, PRIMARY KEY(y)); 23 + INSERT INTO target VALUES(1, 2, 3); 24 + INSERT INTO target VALUES(4, 5, 6); 25 + 26 + ATTACH 'ota.db' AS ota; 27 + CREATE TABLE ota.data_target(x, y, z, ota_control); 28 + INSERT INTO data_target VALUES(7, 8, 9, 0); 29 + INSERT INTO data_target VALUES(1, 11, 12, 0); 30 + DETACH ota; 31 +} 32 +db close 33 + 34 +forcecopy test.db test.db-bak 35 +forcecopy ota.db ota.db-bak 36 + 37 +do_faultsim_test 1 -faults oom* -prep { 38 + forcecopy test.db-bak test.db 39 + forcecopy ota.db-bak ota.db 40 + forcedelete test.db-oal test.db-wal ota.db-journal 41 + sqlite3ota ota test.db ota.db 42 +} -body { 43 + while {[ota step]=="SQLITE_OK"} { } 44 + ota close 45 +} -test { 46 + faultsim_test_result \ 47 + {1 {SQLITE_CONSTRAINT - UNIQUE constraint failed: target.x}} \ 48 + {1 SQLITE_CONSTRAINT} \ 49 + {1 SQLITE_NOMEM} \ 50 + {1 {SQLITE_NOMEM - unable to open a temporary database file for storing temporary tables}} \ 51 + {1 {SQLITE_NOMEM - out of memory}} 52 +} 53 + 54 + 55 + 56 + 57 +finish_test 58 +
Added ext/ota/sqlite3ota.c.
1 +/* 2 +** 2014 August 30 3 +** 4 +** The author disclaims copyright to this source code. In place of 5 +** a legal notice, here is a blessing: 6 +** 7 +** May you do good and not evil. 8 +** May you find forgiveness for yourself and forgive others. 9 +** May you share freely, never taking more than you give. 10 +** 11 +************************************************************************* 12 +** 13 +** 14 +** OVERVIEW 15 +** 16 +** The OTA extension requires that the OTA update be packaged as an 17 +** SQLite database. The tables it expects to find are described in 18 +** sqlite3ota.h. Essentially, for each table xyz in the target database 19 +** that the user wishes to write to, a corresponding data_xyz table is 20 +** created in the OTA database and populated with one row for each row to 21 +** update, insert or delete from the target table. 22 +** 23 +** The update proceeds in three stages: 24 +** 25 +** 1) The database is updated. The modified database pages are written 26 +** to a *-oal file. A *-oal file is just like a *-wal file, except 27 +** that it is named "<database>-oal" instead of "<database>-wal". 28 +** Because regular SQLite clients do not look for file named 29 +** "<database>-oal", they go on using the original database in 30 +** rollback mode while the *-oal file is being generated. 31 +** 32 +** During this stage OTA does not update the database by writing 33 +** directly to the target tables. Instead it creates "imposter" 34 +** tables using the SQLITE_TESTCTRL_IMPOSTER interface that it uses 35 +** to update each b-tree individually. All updates required by each 36 +** b-tree are completed before moving on to the next, and all 37 +** updates are done in sorted key order. 38 +** 39 +** 2) The "<database>-oal" file is moved to the equivalent "<database>-wal" 40 +** location using a call to rename(2). Before doing this the OTA 41 +** module takes an EXCLUSIVE lock on the database file, ensuring 42 +** that there are no other active readers. 43 +** 44 +** Once the EXCLUSIVE lock is released, any other database readers 45 +** detect the new *-wal file and read the database in wal mode. At 46 +** this point they see the new version of the database - including 47 +** the updates made as part of the OTA update. 48 +** 49 +** 3) The new *-wal file is checkpointed. This proceeds in the same way 50 +** as a regular database checkpoint, except that a single frame is 51 +** checkpointed each time sqlite3ota_step() is called. If the OTA 52 +** handle is closed before the entire *-wal file is checkpointed, 53 +** the checkpoint progress is saved in the OTA database and the 54 +** checkpoint can be resumed by another OTA client at some point in 55 +** the future. 56 +** 57 +** POTENTIAL PROBLEMS 58 +** 59 +** The rename() call might not be portable. And OTA is not currently 60 +** syncing the directory after renaming the file. 61 +** 62 +** When state is saved, any commit to the *-oal file and the commit to 63 +** the OTA update database are not atomic. So if the power fails at the 64 +** wrong moment they might get out of sync. As the main database will be 65 +** committed before the OTA update database this will likely either just 66 +** pass unnoticed, or result in SQLITE_CONSTRAINT errors (due to UNIQUE 67 +** constraint violations). 68 +** 69 +** If some client does modify the target database mid OTA update, or some 70 +** other error occurs, the OTA extension will keep throwing errors. It's 71 +** not really clear how to get out of this state. The system could just 72 +** by delete the OTA update database and *-oal file and have the device 73 +** download the update again and start over. 74 +** 75 +** At present, for an UPDATE, both the new.* and old.* records are 76 +** collected in the ota_xyz table. And for both UPDATEs and DELETEs all 77 +** fields are collected. This means we're probably writing a lot more 78 +** data to disk when saving the state of an ongoing update to the OTA 79 +** update database than is strictly necessary. 80 +** 81 +*/ 82 + 83 +#include <assert.h> 84 +#include <string.h> 85 +#include <stdio.h> 86 +#include <unistd.h> 87 + 88 +#include "sqlite3.h" 89 + 90 +#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_OTA) 91 +#include "sqlite3ota.h" 92 + 93 +/* Maximum number of prepared UPDATE statements held by this module */ 94 +#define SQLITE_OTA_UPDATE_CACHESIZE 16 95 + 96 +/* 97 +** Swap two objects of type TYPE. 98 +*/ 99 +#if !defined(SQLITE_AMALGAMATION) 100 +# define SWAP(TYPE,A,B) {TYPE t=A; A=B; B=t;} 101 +#endif 102 + 103 +/* 104 +** The ota_state table is used to save the state of a partially applied 105 +** update so that it can be resumed later. The table consists of integer 106 +** keys mapped to values as follows: 107 +** 108 +** OTA_STATE_STAGE: 109 +** May be set to integer values 1, 2, 4 or 5. As follows: 110 +** 1: the *-ota file is currently under construction. 111 +** 2: the *-ota file has been constructed, but not yet moved 112 +** to the *-wal path. 113 +** 4: the checkpoint is underway. 114 +** 5: the ota update has been checkpointed. 115 +** 116 +** OTA_STATE_TBL: 117 +** Only valid if STAGE==1. The target database name of the table 118 +** currently being written. 119 +** 120 +** OTA_STATE_IDX: 121 +** Only valid if STAGE==1. The target database name of the index 122 +** currently being written, or NULL if the main table is currently being 123 +** updated. 124 +** 125 +** OTA_STATE_ROW: 126 +** Only valid if STAGE==1. Number of rows already processed for the current 127 +** table/index. 128 +** 129 +** OTA_STATE_PROGRESS: 130 +** Total number of sqlite3ota_step() calls made so far as part of this 131 +** ota update. 132 +** 133 +** OTA_STATE_CKPT: 134 +** Valid if STAGE==4. The 64-bit checksum associated with the wal-index 135 +** header created by recovering the *-wal file. This is used to detect 136 +** cases when another client appends frames to the *-wal file in the 137 +** middle of an incremental checkpoint (an incremental checkpoint cannot 138 +** be continued if this happens). 139 +** 140 +** OTA_STATE_COOKIE: 141 +** Valid if STAGE==1. The current change-counter cookie value in the 142 +** target db file. 143 +** 144 +** OTA_STATE_OALSZ: 145 +** Valid if STAGE==1. The size in bytes of the *-oal file. 146 +*/ 147 +#define OTA_STATE_STAGE 1 148 +#define OTA_STATE_TBL 2 149 +#define OTA_STATE_IDX 3 150 +#define OTA_STATE_ROW 4 151 +#define OTA_STATE_PROGRESS 5 152 +#define OTA_STATE_CKPT 6 153 +#define OTA_STATE_COOKIE 7 154 +#define OTA_STATE_OALSZ 8 155 + 156 +#define OTA_STAGE_OAL 1 157 +#define OTA_STAGE_MOVE 2 158 +#define OTA_STAGE_CAPTURE 3 159 +#define OTA_STAGE_CKPT 4 160 +#define OTA_STAGE_DONE 5 161 + 162 + 163 +#define OTA_CREATE_STATE \ 164 + "CREATE TABLE IF NOT EXISTS %s.ota_state(k INTEGER PRIMARY KEY, v)" 165 + 166 +typedef struct OtaFrame OtaFrame; 167 +typedef struct OtaObjIter OtaObjIter; 168 +typedef struct OtaState OtaState; 169 +typedef struct ota_vfs ota_vfs; 170 +typedef struct ota_file ota_file; 171 +typedef struct OtaUpdateStmt OtaUpdateStmt; 172 + 173 +#if !defined(SQLITE_AMALGAMATION) 174 +typedef unsigned int u32; 175 +typedef unsigned char u8; 176 +typedef sqlite3_int64 i64; 177 +#endif 178 + 179 +/* 180 +** These values must match the values defined in wal.c for the equivalent 181 +** locks. These are not magic numbers as they are part of the SQLite file 182 +** format. 183 +*/ 184 +#define WAL_LOCK_WRITE 0 185 +#define WAL_LOCK_CKPT 1 186 +#define WAL_LOCK_READ0 3 187 + 188 +/* 189 +** A structure to store values read from the ota_state table in memory. 190 +*/ 191 +struct OtaState { 192 + int eStage; 193 + char *zTbl; 194 + char *zIdx; 195 + i64 iWalCksum; 196 + int nRow; 197 + i64 nProgress; 198 + u32 iCookie; 199 + i64 iOalSz; 200 +}; 201 + 202 +struct OtaUpdateStmt { 203 + char *zMask; /* Copy of update mask used with pUpdate */ 204 + sqlite3_stmt *pUpdate; /* Last update statement (or NULL) */ 205 + OtaUpdateStmt *pNext; 206 +}; 207 + 208 +/* 209 +** An iterator of this type is used to iterate through all objects in 210 +** the target database that require updating. For each such table, the 211 +** iterator visits, in order: 212 +** 213 +** * the table itself, 214 +** * each index of the table (zero or more points to visit), and 215 +** * a special "cleanup table" state. 216 +** 217 +** abIndexed: 218 +** If the table has no indexes on it, abIndexed is set to NULL. Otherwise, 219 +** it points to an array of flags nTblCol elements in size. The flag is 220 +** set for each column that is either a part of the PK or a part of an 221 +** index. Or clear otherwise. 222 +** 223 +*/ 224 +struct OtaObjIter { 225 + sqlite3_stmt *pTblIter; /* Iterate through tables */ 226 + sqlite3_stmt *pIdxIter; /* Index iterator */ 227 + int nTblCol; /* Size of azTblCol[] array */ 228 + char **azTblCol; /* Array of unquoted target column names */ 229 + char **azTblType; /* Array of target column types */ 230 + int *aiSrcOrder; /* src table col -> target table col */ 231 + u8 *abTblPk; /* Array of flags, set on target PK columns */ 232 + u8 *abNotNull; /* Array of flags, set on NOT NULL columns */ 233 + u8 *abIndexed; /* Array of flags, set on indexed & PK cols */ 234 + int eType; /* Table type - an OTA_PK_XXX value */ 235 + 236 + /* Output variables. zTbl==0 implies EOF. */ 237 + int bCleanup; /* True in "cleanup" state */ 238 + const char *zTbl; /* Name of target db table */ 239 + const char *zIdx; /* Name of target db index (or null) */ 240 + int iTnum; /* Root page of current object */ 241 + int iPkTnum; /* If eType==EXTERNAL, root of PK index */ 242 + int bUnique; /* Current index is unique */ 243 + 244 + /* Statements created by otaObjIterPrepareAll() */ 245 + int nCol; /* Number of columns in current object */ 246 + sqlite3_stmt *pSelect; /* Source data */ 247 + sqlite3_stmt *pInsert; /* Statement for INSERT operations */ 248 + sqlite3_stmt *pDelete; /* Statement for DELETE ops */ 249 + sqlite3_stmt *pTmpInsert; /* Insert into ota_tmp_$zTbl */ 250 + 251 + /* Last UPDATE used (for PK b-tree updates only), or NULL. */ 252 + OtaUpdateStmt *pOtaUpdate; 253 +}; 254 + 255 +/* 256 +** Values for OtaObjIter.eType 257 +** 258 +** 0: Table does not exist (error) 259 +** 1: Table has an implicit rowid. 260 +** 2: Table has an explicit IPK column. 261 +** 3: Table has an external PK index. 262 +** 4: Table is WITHOUT ROWID. 263 +** 5: Table is a virtual table. 264 +*/ 265 +#define OTA_PK_NOTABLE 0 266 +#define OTA_PK_NONE 1 267 +#define OTA_PK_IPK 2 268 +#define OTA_PK_EXTERNAL 3 269 +#define OTA_PK_WITHOUT_ROWID 4 270 +#define OTA_PK_VTAB 5 271 + 272 + 273 +/* 274 +** Within the OTA_STAGE_OAL stage, each call to sqlite3ota_step() performs 275 +** one of the following operations. 276 +*/ 277 +#define OTA_INSERT 1 /* Insert on a main table b-tree */ 278 +#define OTA_DELETE 2 /* Delete a row from a main table b-tree */ 279 +#define OTA_IDX_DELETE 3 /* Delete a row from an aux. index b-tree */ 280 +#define OTA_IDX_INSERT 4 /* Insert on an aux. index b-tree */ 281 +#define OTA_UPDATE 5 /* Update a row in a main table b-tree */ 282 + 283 + 284 +/* 285 +** A single step of an incremental checkpoint - frame iWalFrame of the wal 286 +** file should be copied to page iDbPage of the database file. 287 +*/ 288 +struct OtaFrame { 289 + u32 iDbPage; 290 + u32 iWalFrame; 291 +}; 292 + 293 +/* 294 +** OTA handle. 295 +*/ 296 +struct sqlite3ota { 297 + int eStage; /* Value of OTA_STATE_STAGE field */ 298 + sqlite3 *dbMain; /* target database handle */ 299 + sqlite3 *dbOta; /* ota database handle */ 300 + char *zTarget; /* Path to target db */ 301 + char *zOta; /* Path to ota db */ 302 + char *zState; /* Path to state db (or NULL if zOta) */ 303 + char zStateDb[5]; /* Db name for state ("stat" or "main") */ 304 + int rc; /* Value returned by last ota_step() call */ 305 + char *zErrmsg; /* Error message if rc!=SQLITE_OK */ 306 + int nStep; /* Rows processed for current object */ 307 + int nProgress; /* Rows processed for all objects */ 308 + OtaObjIter objiter; /* Iterator for skipping through tbl/idx */ 309 + const char *zVfsName; /* Name of automatically created ota vfs */ 310 + ota_file *pTargetFd; /* File handle open on target db */ 311 + i64 iOalSz; 312 + 313 + /* The following state variables are used as part of the incremental 314 + ** checkpoint stage (eStage==OTA_STAGE_CKPT). See comments surrounding 315 + ** function otaSetupCheckpoint() for details. */ 316 + u32 iMaxFrame; /* Largest iWalFrame value in aFrame[] */ 317 + u32 mLock; 318 + int nFrame; /* Entries in aFrame[] array */ 319 + int nFrameAlloc; /* Allocated size of aFrame[] array */ 320 + OtaFrame *aFrame; 321 + int pgsz; 322 + u8 *aBuf; 323 + i64 iWalCksum; 324 +}; 325 + 326 +/* 327 +** An ota VFS is implemented using an instance of this structure. 328 +*/ 329 +struct ota_vfs { 330 + sqlite3_vfs base; /* ota VFS shim methods */ 331 + sqlite3_vfs *pRealVfs; /* Underlying VFS */ 332 + sqlite3_mutex *mutex; /* Mutex to protect pMain */ 333 + ota_file *pMain; /* Linked list of main db files */ 334 +}; 335 + 336 +/* 337 +** Each file opened by an ota VFS is represented by an instance of 338 +** the following structure. 339 +*/ 340 +struct ota_file { 341 + sqlite3_file base; /* sqlite3_file methods */ 342 + sqlite3_file *pReal; /* Underlying file handle */ 343 + ota_vfs *pOtaVfs; /* Pointer to the ota_vfs object */ 344 + sqlite3ota *pOta; /* Pointer to ota object (ota target only) */ 345 + 346 + int openFlags; /* Flags this file was opened with */ 347 + u32 iCookie; /* Cookie value for main db files */ 348 + u8 iWriteVer; /* "write-version" value for main db files */ 349 + 350 + int nShm; /* Number of entries in apShm[] array */ 351 + char **apShm; /* Array of mmap'd *-shm regions */ 352 + char *zDel; /* Delete this when closing file */ 353 + 354 + const char *zWal; /* Wal filename for this main db file */ 355 + ota_file *pWalFd; /* Wal file descriptor for this main db */ 356 + ota_file *pMainNext; /* Next MAIN_DB file */ 357 +}; 358 + 359 + 360 +/* 361 +** Prepare the SQL statement in buffer zSql against database handle db. 362 +** If successful, set *ppStmt to point to the new statement and return 363 +** SQLITE_OK. 364 +** 365 +** Otherwise, if an error does occur, set *ppStmt to NULL and return 366 +** an SQLite error code. Additionally, set output variable *pzErrmsg to 367 +** point to a buffer containing an error message. It is the responsibility 368 +** of the caller to (eventually) free this buffer using sqlite3_free(). 369 +*/ 370 +static int prepareAndCollectError( 371 + sqlite3 *db, 372 + sqlite3_stmt **ppStmt, 373 + char **pzErrmsg, 374 + const char *zSql 375 +){ 376 + int rc = sqlite3_prepare_v2(db, zSql, -1, ppStmt, 0); 377 + if( rc!=SQLITE_OK ){ 378 + *pzErrmsg = sqlite3_mprintf("%s", sqlite3_errmsg(db)); 379 + *ppStmt = 0; 380 + } 381 + return rc; 382 +} 383 + 384 +/* 385 +** Reset the SQL statement passed as the first argument. Return a copy 386 +** of the value returned by sqlite3_reset(). 387 +** 388 +** If an error has occurred, then set *pzErrmsg to point to a buffer 389 +** containing an error message. It is the responsibility of the caller 390 +** to eventually free this buffer using sqlite3_free(). 391 +*/ 392 +static int resetAndCollectError(sqlite3_stmt *pStmt, char **pzErrmsg){ 393 + int rc = sqlite3_reset(pStmt); 394 + if( rc!=SQLITE_OK ){ 395 + *pzErrmsg = sqlite3_mprintf("%s", sqlite3_errmsg(sqlite3_db_handle(pStmt))); 396 + } 397 + return rc; 398 +} 399 + 400 +/* 401 +** Unless it is NULL, argument zSql points to a buffer allocated using 402 +** sqlite3_malloc containing an SQL statement. This function prepares the SQL 403 +** statement against database db and frees the buffer. If statement 404 +** compilation is successful, *ppStmt is set to point to the new statement 405 +** handle and SQLITE_OK is returned. 406 +** 407 +** Otherwise, if an error occurs, *ppStmt is set to NULL and an error code 408 +** returned. In this case, *pzErrmsg may also be set to point to an error 409 +** message. It is the responsibility of the caller to free this error message 410 +** buffer using sqlite3_free(). 411 +** 412 +** If argument zSql is NULL, this function assumes that an OOM has occurred. 413 +** In this case SQLITE_NOMEM is returned and *ppStmt set to NULL. 414 +*/ 415 +static int prepareFreeAndCollectError( 416 + sqlite3 *db, 417 + sqlite3_stmt **ppStmt, 418 + char **pzErrmsg, 419 + char *zSql 420 +){ 421 + int rc; 422 + assert( *pzErrmsg==0 ); 423 + if( zSql==0 ){ 424 + rc = SQLITE_NOMEM; 425 + *ppStmt = 0; 426 + }else{ 427 + rc = prepareAndCollectError(db, ppStmt, pzErrmsg, zSql); 428 + sqlite3_free(zSql); 429 + } 430 + return rc; 431 +} 432 + 433 +/* 434 +** Free the OtaObjIter.azTblCol[] and OtaObjIter.abTblPk[] arrays allocated 435 +** by an earlier call to otaObjIterCacheTableInfo(). 436 +*/ 437 +static void otaObjIterFreeCols(OtaObjIter *pIter){ 438 + int i; 439 + for(i=0; i<pIter->nTblCol; i++){ 440 + sqlite3_free(pIter->azTblCol[i]); 441 + sqlite3_free(pIter->azTblType[i]); 442 + } 443 + sqlite3_free(pIter->azTblCol); 444 + pIter->azTblCol = 0; 445 + pIter->azTblType = 0; 446 + pIter->aiSrcOrder = 0; 447 + pIter->abTblPk = 0; 448 + pIter->abNotNull = 0; 449 + pIter->nTblCol = 0; 450 + pIter->eType = 0; /* Invalid value */ 451 +} 452 + 453 +/* 454 +** Finalize all statements and free all allocations that are specific to 455 +** the current object (table/index pair). 456 +*/ 457 +static void otaObjIterClearStatements(OtaObjIter *pIter){ 458 + OtaUpdateStmt *pUp; 459 + 460 + sqlite3_finalize(pIter->pSelect); 461 + sqlite3_finalize(pIter->pInsert); 462 + sqlite3_finalize(pIter->pDelete); 463 + sqlite3_finalize(pIter->pTmpInsert); 464 + pUp = pIter->pOtaUpdate; 465 + while( pUp ){ 466 + OtaUpdateStmt *pTmp = pUp->pNext; 467 + sqlite3_finalize(pUp->pUpdate); 468 + sqlite3_free(pUp); 469 + pUp = pTmp; 470 + } 471 + 472 + pIter->pSelect = 0; 473 + pIter->pInsert = 0; 474 + pIter->pDelete = 0; 475 + pIter->pOtaUpdate = 0; 476 + pIter->pTmpInsert = 0; 477 + pIter->nCol = 0; 478 +} 479 + 480 +/* 481 +** Clean up any resources allocated as part of the iterator object passed 482 +** as the only argument. 483 +*/ 484 +static void otaObjIterFinalize(OtaObjIter *pIter){ 485 + otaObjIterClearStatements(pIter); 486 + sqlite3_finalize(pIter->pTblIter); 487 + sqlite3_finalize(pIter->pIdxIter); 488 + otaObjIterFreeCols(pIter); 489 + memset(pIter, 0, sizeof(OtaObjIter)); 490 +} 491 + 492 +/* 493 +** Advance the iterator to the next position. 494 +** 495 +** If no error occurs, SQLITE_OK is returned and the iterator is left 496 +** pointing to the next entry. Otherwise, an error code and message is 497 +** left in the OTA handle passed as the first argument. A copy of the 498 +** error code is returned. 499 +*/ 500 +static int otaObjIterNext(sqlite3ota *p, OtaObjIter *pIter){ 501 + int rc = p->rc; 502 + if( rc==SQLITE_OK ){ 503 + 504 + /* Free any SQLite statements used while processing the previous object */ 505 + otaObjIterClearStatements(pIter); 506 + if( pIter->zIdx==0 ){ 507 + rc = sqlite3_exec(p->dbMain, 508 + "DROP TRIGGER IF EXISTS temp.ota_insert_tr;" 509 + "DROP TRIGGER IF EXISTS temp.ota_update1_tr;" 510 + "DROP TRIGGER IF EXISTS temp.ota_update2_tr;" 511 + "DROP TRIGGER IF EXISTS temp.ota_delete_tr;" 512 + , 0, 0, &p->zErrmsg 513 + ); 514 + } 515 + 516 + if( rc==SQLITE_OK ){ 517 + if( pIter->bCleanup ){ 518 + otaObjIterFreeCols(pIter); 519 + pIter->bCleanup = 0; 520 + rc = sqlite3_step(pIter->pTblIter); 521 + if( rc!=SQLITE_ROW ){ 522 + rc = resetAndCollectError(pIter->pTblIter, &p->zErrmsg); 523 + pIter->zTbl = 0; 524 + }else{ 525 + pIter->zTbl = (const char*)sqlite3_column_text(pIter->pTblIter, 0); 526 + rc = pIter->zTbl ? SQLITE_OK : SQLITE_NOMEM; 527 + } 528 + }else{ 529 + if( pIter->zIdx==0 ){ 530 + sqlite3_stmt *pIdx = pIter->pIdxIter; 531 + rc = sqlite3_bind_text(pIdx, 1, pIter->zTbl, -1, SQLITE_STATIC); 532 + } 533 + if( rc==SQLITE_OK ){ 534 + rc = sqlite3_step(pIter->pIdxIter); 535 + if( rc!=SQLITE_ROW ){ 536 + rc = resetAndCollectError(pIter->pIdxIter, &p->zErrmsg); 537 + pIter->bCleanup = 1; 538 + pIter->zIdx = 0; 539 + }else{ 540 + pIter->zIdx = (const char*)sqlite3_column_text(pIter->pIdxIter, 0); 541 + pIter->iTnum = sqlite3_column_int(pIter->pIdxIter, 1); 542 + pIter->bUnique = sqlite3_column_int(pIter->pIdxIter, 2); 543 + rc = pIter->zIdx ? SQLITE_OK : SQLITE_NOMEM; 544 + } 545 + } 546 + } 547 + } 548 + } 549 + 550 + if( rc!=SQLITE_OK ){ 551 + otaObjIterFinalize(pIter); 552 + p->rc = rc; 553 + } 554 + return rc; 555 +} 556 + 557 +/* 558 +** Initialize the iterator structure passed as the second argument. 559 +** 560 +** If no error occurs, SQLITE_OK is returned and the iterator is left 561 +** pointing to the first entry. Otherwise, an error code and message is 562 +** left in the OTA handle passed as the first argument. A copy of the 563 +** error code is returned. 564 +*/ 565 +static int otaObjIterFirst(sqlite3ota *p, OtaObjIter *pIter){ 566 + int rc; 567 + memset(pIter, 0, sizeof(OtaObjIter)); 568 + 569 + rc = prepareAndCollectError(p->dbOta, &pIter->pTblIter, &p->zErrmsg, 570 + "SELECT substr(name, 6) FROM sqlite_master " 571 + "WHERE type='table' AND name LIKE 'data_%'" 572 + ); 573 + 574 + if( rc==SQLITE_OK ){ 575 + rc = prepareAndCollectError(p->dbMain, &pIter->pIdxIter, &p->zErrmsg, 576 + "SELECT name, rootpage, sql IS NULL OR substr(8, 6)=='UNIQUE' " 577 + " FROM main.sqlite_master " 578 + " WHERE type='index' AND tbl_name = ?" 579 + ); 580 + } 581 + 582 + pIter->bCleanup = 1; 583 + p->rc = rc; 584 + return otaObjIterNext(p, pIter); 585 +} 586 + 587 +/* 588 +** This is a wrapper around "sqlite3_mprintf(zFmt, ...)". If an OOM occurs, 589 +** an error code is stored in the OTA handle passed as the first argument. 590 +** 591 +** If an error has already occurred (p->rc is already set to something other 592 +** than SQLITE_OK), then this function returns NULL without modifying the 593 +** stored error code. In this case it still calls sqlite3_free() on any 594 +** printf() parameters associated with %z conversions. 595 +*/ 596 +static char *otaMPrintf(sqlite3ota *p, const char *zFmt, ...){ 597 + char *zSql = 0; 598 + va_list ap; 599 + va_start(ap, zFmt); 600 + zSql = sqlite3_vmprintf(zFmt, ap); 601 + if( p->rc==SQLITE_OK ){ 602 + if( zSql==0 ) p->rc = SQLITE_NOMEM; 603 + }else{ 604 + sqlite3_free(zSql); 605 + zSql = 0; 606 + } 607 + va_end(ap); 608 + return zSql; 609 +} 610 + 611 +/* 612 +** Argument zFmt is a sqlite3_mprintf() style format string. The trailing 613 +** arguments are the usual subsitution values. This function performs 614 +** the printf() style substitutions and executes the result as an SQL 615 +** statement on the OTA handles database. 616 +** 617 +** If an error occurs, an error code and error message is stored in the 618 +** OTA handle. If an error has already occurred when this function is 619 +** called, it is a no-op. 620 +*/ 621 +static int otaMPrintfExec(sqlite3ota *p, sqlite3 *db, const char *zFmt, ...){ 622 + va_list ap; 623 + va_start(ap, zFmt); 624 + char *zSql = sqlite3_vmprintf(zFmt, ap); 625 + if( p->rc==SQLITE_OK ){ 626 + if( zSql==0 ){ 627 + p->rc = SQLITE_NOMEM; 628 + }else{ 629 + p->rc = sqlite3_exec(db, zSql, 0, 0, &p->zErrmsg); 630 + } 631 + } 632 + sqlite3_free(zSql); 633 + va_end(ap); 634 + return p->rc; 635 +} 636 + 637 +/* 638 +** Attempt to allocate and return a pointer to a zeroed block of nByte 639 +** bytes. 640 +** 641 +** If an error (i.e. an OOM condition) occurs, return NULL and leave an 642 +** error code in the ota handle passed as the first argument. Or, if an 643 +** error has already occurred when this function is called, return NULL 644 +** immediately without attempting the allocation or modifying the stored 645 +** error code. 646 +*/ 647 +static void *otaMalloc(sqlite3ota *p, int nByte){ 648 + void *pRet = 0; 649 + if( p->rc==SQLITE_OK ){ 650 + assert( nByte>0 ); 651 + pRet = sqlite3_malloc(nByte); 652 + if( pRet==0 ){ 653 + p->rc = SQLITE_NOMEM; 654 + }else{ 655 + memset(pRet, 0, nByte); 656 + } 657 + } 658 + return pRet; 659 +} 660 + 661 + 662 +/* 663 +** Allocate and zero the pIter->azTblCol[] and abTblPk[] arrays so that 664 +** there is room for at least nCol elements. If an OOM occurs, store an 665 +** error code in the OTA handle passed as the first argument. 666 +*/ 667 +static void otaAllocateIterArrays(sqlite3ota *p, OtaObjIter *pIter, int nCol){ 668 + int nByte = (2*sizeof(char*) + sizeof(int) + 3*sizeof(u8)) * nCol; 669 + char **azNew; 670 + 671 + azNew = (char**)otaMalloc(p, nByte); 672 + if( azNew ){ 673 + pIter->azTblCol = azNew; 674 + pIter->azTblType = &azNew[nCol]; 675 + pIter->aiSrcOrder = (int*)&pIter->azTblType[nCol]; 676 + pIter->abTblPk = (u8*)&pIter->aiSrcOrder[nCol]; 677 + pIter->abNotNull = (u8*)&pIter->abTblPk[nCol]; 678 + pIter->abIndexed = (u8*)&pIter->abNotNull[nCol]; 679 + } 680 +} 681 + 682 +/* 683 +** The first argument must be a nul-terminated string. This function 684 +** returns a copy of the string in memory obtained from sqlite3_malloc(). 685 +** It is the responsibility of the caller to eventually free this memory 686 +** using sqlite3_free(). 687 +** 688 +** If an OOM condition is encountered when attempting to allocate memory, 689 +** output variable (*pRc) is set to SQLITE_NOMEM before returning. Otherwise, 690 +** if the allocation succeeds, (*pRc) is left unchanged. 691 +*/ 692 +static char *otaStrndup(const char *zStr, int *pRc){ 693 + char *zRet = 0; 694 + 695 + assert( *pRc==SQLITE_OK ); 696 + if( zStr ){ 697 + int nCopy = strlen(zStr) + 1; 698 + zRet = (char*)sqlite3_malloc(nCopy); 699 + if( zRet ){ 700 + memcpy(zRet, zStr, nCopy); 701 + }else{ 702 + *pRc = SQLITE_NOMEM; 703 + } 704 + } 705 + 706 + return zRet; 707 +} 708 + 709 +/* 710 +** Finalize the statement passed as the second argument. 711 +** 712 +** If the sqlite3_finalize() call indicates that an error occurs, and the 713 +** ota handle error code is not already set, set the error code and error 714 +** message accordingly. 715 +*/ 716 +static void otaFinalize(sqlite3ota *p, sqlite3_stmt *pStmt){ 717 + sqlite3 *db = sqlite3_db_handle(pStmt); 718 + int rc = sqlite3_finalize(pStmt); 719 + if( p->rc==SQLITE_OK && rc!=SQLITE_OK ){ 720 + p->rc = rc; 721 + p->zErrmsg = sqlite3_mprintf("%s", sqlite3_errmsg(db)); 722 + } 723 +} 724 + 725 +/* Determine the type of a table. 726 +** 727 +** peType is of type (int*), a pointer to an output parameter of type 728 +** (int). This call sets the output parameter as follows, depending 729 +** on the type of the table specified by parameters dbName and zTbl. 730 +** 731 +** OTA_PK_NOTABLE: No such table. 732 +** OTA_PK_NONE: Table has an implicit rowid. 733 +** OTA_PK_IPK: Table has an explicit IPK column. 734 +** OTA_PK_EXTERNAL: Table has an external PK index. 735 +** OTA_PK_WITHOUT_ROWID: Table is WITHOUT ROWID. 736 +** OTA_PK_VTAB: Table is a virtual table. 737 +** 738 +** Argument *piPk is also of type (int*), and also points to an output 739 +** parameter. Unless the table has an external primary key index 740 +** (i.e. unless *peType is set to 3), then *piPk is set to zero. Or, 741 +** if the table does have an external primary key index, then *piPk 742 +** is set to the root page number of the primary key index before 743 +** returning. 744 +** 745 +** ALGORITHM: 746 +** 747 +** if( no entry exists in sqlite_master ){ 748 +** return OTA_PK_NOTABLE 749 +** }else if( sql for the entry starts with "CREATE VIRTUAL" ){ 750 +** return OTA_PK_VTAB 751 +** }else if( "PRAGMA index_list()" for the table contains a "pk" index ){ 752 +** if( the index that is the pk exists in sqlite_master ){ 753 +** *piPK = rootpage of that index. 754 +** return OTA_PK_EXTERNAL 755 +** }else{ 756 +** return OTA_PK_WITHOUT_ROWID 757 +** } 758 +** }else if( "PRAGMA table_info()" lists one or more "pk" columns ){ 759 +** return OTA_PK_IPK 760 +** }else{ 761 +** return OTA_PK_NONE 762 +** } 763 +*/ 764 +static void otaTableType( 765 + sqlite3ota *p, 766 + const char *zTab, 767 + int *peType, 768 + int *piTnum, 769 + int *piPk 770 +){ 771 + /* 772 + ** 0) SELECT count(*) FROM sqlite_master where name=%Q AND IsVirtual(%Q) 773 + ** 1) PRAGMA index_list = ? 774 + ** 2) SELECT count(*) FROM sqlite_master where name=%Q 775 + ** 3) PRAGMA table_info = ? 776 + */ 777 + sqlite3_stmt *aStmt[4] = {0, 0, 0, 0}; 778 + 779 + *peType = OTA_PK_NOTABLE; 780 + *piPk = 0; 781 + 782 + assert( p->rc==SQLITE_OK ); 783 + p->rc = prepareFreeAndCollectError(p->dbMain, &aStmt[0], &p->zErrmsg, 784 + sqlite3_mprintf( 785 + "SELECT (sql LIKE 'create virtual%%'), rootpage" 786 + " FROM sqlite_master" 787 + " WHERE name=%Q", zTab 788 + )); 789 + if( p->rc!=SQLITE_OK || sqlite3_step(aStmt[0])!=SQLITE_ROW ){ 790 + /* Either an error, or no such table. */ 791 + goto otaTableType_end; 792 + } 793 + if( sqlite3_column_int(aStmt[0], 0) ){ 794 + *peType = OTA_PK_VTAB; /* virtual table */ 795 + goto otaTableType_end; 796 + } 797 + *piTnum = sqlite3_column_int(aStmt[0], 1); 798 + 799 + p->rc = prepareFreeAndCollectError(p->dbMain, &aStmt[1], &p->zErrmsg, 800 + sqlite3_mprintf("PRAGMA index_list=%Q",zTab) 801 + ); 802 + if( p->rc ) goto otaTableType_end; 803 + while( sqlite3_step(aStmt[1])==SQLITE_ROW ){ 804 + const u8 *zOrig = sqlite3_column_text(aStmt[1], 3); 805 + const u8 *zIdx = sqlite3_column_text(aStmt[1], 1); 806 + if( zOrig && zIdx && zOrig[0]=='p' ){ 807 + p->rc = prepareFreeAndCollectError(p->dbMain, &aStmt[2], &p->zErrmsg, 808 + sqlite3_mprintf( 809 + "SELECT rootpage FROM sqlite_master WHERE name = %Q", zIdx 810 + )); 811 + if( p->rc==SQLITE_OK ){ 812 + if( sqlite3_step(aStmt[2])==SQLITE_ROW ){ 813 + *piPk = sqlite3_column_int(aStmt[2], 0); 814 + *peType = OTA_PK_EXTERNAL; 815 + }else{ 816 + *peType = OTA_PK_WITHOUT_ROWID; 817 + } 818 + } 819 + goto otaTableType_end; 820 + } 821 + } 822 + 823 + p->rc = prepareFreeAndCollectError(p->dbMain, &aStmt[3], &p->zErrmsg, 824 + sqlite3_mprintf("PRAGMA table_info=%Q",zTab) 825 + ); 826 + if( p->rc==SQLITE_OK ){ 827 + while( sqlite3_step(aStmt[3])==SQLITE_ROW ){ 828 + if( sqlite3_column_int(aStmt[3],5)>0 ){ 829 + *peType = OTA_PK_IPK; /* explicit IPK column */ 830 + goto otaTableType_end; 831 + } 832 + } 833 + *peType = OTA_PK_NONE; 834 + } 835 + 836 +otaTableType_end: { 837 + int i; 838 + for(i=0; i<sizeof(aStmt)/sizeof(aStmt[0]); i++){ 839 + otaFinalize(p, aStmt[i]); 840 + } 841 + } 842 +} 843 + 844 +/* 845 +** This is a helper function for otaObjIterCacheTableInfo(). It populates 846 +** the pIter->abIndexed[] array. 847 +*/ 848 +static void otaObjIterCacheIndexedCols(sqlite3ota *p, OtaObjIter *pIter){ 849 + sqlite3_stmt *pList = 0; 850 + int bIndex = 0; 851 + 852 + if( p->rc==SQLITE_OK ){ 853 + memcpy(pIter->abIndexed, pIter->abTblPk, sizeof(u8)*pIter->nTblCol); 854 + p->rc = prepareFreeAndCollectError(p->dbMain, &pList, &p->zErrmsg, 855 + sqlite3_mprintf("PRAGMA main.index_list = %Q", pIter->zTbl) 856 + ); 857 + } 858 + 859 + while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pList) ){ 860 + const char *zIdx = (const char*)sqlite3_column_text(pList, 1); 861 + sqlite3_stmt *pXInfo = 0; 862 + if( zIdx==0 ) break; 863 + p->rc = prepareFreeAndCollectError(p->dbMain, &pXInfo, &p->zErrmsg, 864 + sqlite3_mprintf("PRAGMA main.index_xinfo = %Q", zIdx) 865 + ); 866 + while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pXInfo) ){ 867 + int iCid = sqlite3_column_int(pXInfo, 1); 868 + if( iCid>=0 ) pIter->abIndexed[iCid] = 1; 869 + } 870 + otaFinalize(p, pXInfo); 871 + bIndex = 1; 872 + } 873 + 874 + otaFinalize(p, pList); 875 + if( bIndex==0 ) pIter->abIndexed = 0; 876 +} 877 + 878 + 879 +/* 880 +** If they are not already populated, populate the pIter->azTblCol[], 881 +** pIter->abTblPk[], pIter->nTblCol and pIter->bRowid variables according to 882 +** the table (not index) that the iterator currently points to. 883 +** 884 +** Return SQLITE_OK if successful, or an SQLite error code otherwise. If 885 +** an error does occur, an error code and error message are also left in 886 +** the OTA handle. 887 +*/ 888 +static int otaObjIterCacheTableInfo(sqlite3ota *p, OtaObjIter *pIter){ 889 + if( pIter->azTblCol==0 ){ 890 + sqlite3_stmt *pStmt = 0; 891 + int nCol = 0; 892 + int i; /* for() loop iterator variable */ 893 + int bOtaRowid = 0; /* If input table has column "ota_rowid" */ 894 + int iOrder = 0; 895 + int iTnum = 0; 896 + 897 + /* Figure out the type of table this step will deal with. */ 898 + assert( pIter->eType==0 ); 899 + otaTableType(p, pIter->zTbl, &pIter->eType, &iTnum, &pIter->iPkTnum); 900 + if( p->rc==SQLITE_OK && pIter->eType==OTA_PK_NOTABLE ){ 901 + p->rc = SQLITE_ERROR; 902 + p->zErrmsg = sqlite3_mprintf("no such table: %s", pIter->zTbl); 903 + } 904 + if( p->rc ) return p->rc; 905 + if( pIter->zIdx==0 ) pIter->iTnum = iTnum; 906 + 907 + assert( pIter->eType==OTA_PK_NONE || pIter->eType==OTA_PK_IPK 908 + || pIter->eType==OTA_PK_EXTERNAL || pIter->eType==OTA_PK_WITHOUT_ROWID 909 + || pIter->eType==OTA_PK_VTAB 910 + ); 911 + 912 + /* Populate the azTblCol[] and nTblCol variables based on the columns 913 + ** of the input table. Ignore any input table columns that begin with 914 + ** "ota_". */ 915 + p->rc = prepareFreeAndCollectError(p->dbOta, &pStmt, &p->zErrmsg, 916 + sqlite3_mprintf("SELECT * FROM 'data_%q'", pIter->zTbl) 917 + ); 918 + if( p->rc==SQLITE_OK ){ 919 + nCol = sqlite3_column_count(pStmt); 920 + otaAllocateIterArrays(p, pIter, nCol); 921 + } 922 + for(i=0; p->rc==SQLITE_OK && i<nCol; i++){ 923 + const char *zName = (const char*)sqlite3_column_name(pStmt, i); 924 + if( sqlite3_strnicmp("ota_", zName, 4) ){ 925 + char *zCopy = otaStrndup(zName, &p->rc); 926 + pIter->aiSrcOrder[pIter->nTblCol] = pIter->nTblCol; 927 + pIter->azTblCol[pIter->nTblCol++] = zCopy; 928 + } 929 + else if( 0==sqlite3_stricmp("ota_rowid", zName) ){ 930 + bOtaRowid = 1; 931 + } 932 + } 933 + sqlite3_finalize(pStmt); 934 + pStmt = 0; 935 + 936 + if( p->rc==SQLITE_OK 937 + && bOtaRowid!=(pIter->eType==OTA_PK_VTAB || pIter->eType==OTA_PK_NONE) 938 + ){ 939 + p->rc = SQLITE_ERROR; 940 + p->zErrmsg = sqlite3_mprintf( 941 + "table data_%q %s ota_rowid column", pIter->zTbl, 942 + (bOtaRowid ? "may not have" : "requires") 943 + ); 944 + } 945 + 946 + /* Check that all non-HIDDEN columns in the destination table are also 947 + ** present in the input table. Populate the abTblPk[], azTblType[] and 948 + ** aiTblOrder[] arrays at the same time. */ 949 + if( p->rc==SQLITE_OK ){ 950 + p->rc = prepareFreeAndCollectError(p->dbMain, &pStmt, &p->zErrmsg, 951 + sqlite3_mprintf("PRAGMA table_info(%Q)", pIter->zTbl) 952 + ); 953 + } 954 + while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ 955 + const char *zName = (const char*)sqlite3_column_text(pStmt, 1); 956 + if( zName==0 ) break; /* An OOM - finalize() below returns S_NOMEM */ 957 + for(i=iOrder; i<pIter->nTblCol; i++){ 958 + if( 0==strcmp(zName, pIter->azTblCol[i]) ) break; 959 + } 960 + if( i==pIter->nTblCol ){ 961 + p->rc = SQLITE_ERROR; 962 + p->zErrmsg = sqlite3_mprintf("column missing from data_%q: %s", 963 + pIter->zTbl, zName 964 + ); 965 + }else{ 966 + int iPk = sqlite3_column_int(pStmt, 5); 967 + int bNotNull = sqlite3_column_int(pStmt, 3); 968 + const char *zType = (const char*)sqlite3_column_text(pStmt, 2); 969 + 970 + if( i!=iOrder ){ 971 + SWAP(int, pIter->aiSrcOrder[i], pIter->aiSrcOrder[iOrder]); 972 + SWAP(char*, pIter->azTblCol[i], pIter->azTblCol[iOrder]); 973 + } 974 + 975 + pIter->azTblType[iOrder] = otaStrndup(zType, &p->rc); 976 + pIter->abTblPk[iOrder] = (iPk!=0); 977 + pIter->abNotNull[iOrder] = (u8)bNotNull || (iPk!=0); 978 + iOrder++; 979 + } 980 + } 981 + 982 + otaFinalize(p, pStmt); 983 + otaObjIterCacheIndexedCols(p, pIter); 984 + assert( pIter->eType!=OTA_PK_VTAB || pIter->abIndexed==0 ); 985 + } 986 + 987 + return p->rc; 988 +} 989 + 990 +/* 991 +** This function constructs and returns a pointer to a nul-terminated 992 +** string containing some SQL clause or list based on one or more of the 993 +** column names currently stored in the pIter->azTblCol[] array. 994 +*/ 995 +static char *otaObjIterGetCollist( 996 + sqlite3ota *p, /* OTA object */ 997 + OtaObjIter *pIter /* Object iterator for column names */ 998 +){ 999 + char *zList = 0; 1000 + const char *zSep = ""; 1001 + int i; 1002 + for(i=0; i<pIter->nTblCol; i++){ 1003 + const char *z = pIter->azTblCol[i]; 1004 + zList = otaMPrintf(p, "%z%s\"%w\"", zList, zSep, z); 1005 + zSep = ", "; 1006 + } 1007 + return zList; 1008 +} 1009 + 1010 +/* 1011 +** This function is used to create a SELECT list (the list of SQL 1012 +** expressions that follows a SELECT keyword) for a SELECT statement 1013 +** used to read from an data_xxx or ota_tmp_xxx table while updating the 1014 +** index object currently indicated by the iterator object passed as the 1015 +** second argument. A "PRAGMA index_xinfo = <idxname>" statement is used 1016 +** to obtain the required information. 1017 +** 1018 +** If the index is of the following form: 1019 +** 1020 +** CREATE INDEX i1 ON t1(c, b COLLATE nocase); 1021 +** 1022 +** and "t1" is a table with an explicit INTEGER PRIMARY KEY column 1023 +** "ipk", the returned string is: 1024 +** 1025 +** "`c` COLLATE 'BINARY', `b` COLLATE 'NOCASE', `ipk` COLLATE 'BINARY'" 1026 +** 1027 +** As well as the returned string, three other malloc'd strings are 1028 +** returned via output parameters. As follows: 1029 +** 1030 +** pzImposterCols: ... 1031 +** pzImposterPk: ... 1032 +** pzWhere: ... 1033 +*/ 1034 +static char *otaObjIterGetIndexCols( 1035 + sqlite3ota *p, /* OTA object */ 1036 + OtaObjIter *pIter, /* Object iterator for column names */ 1037 + char **pzImposterCols, /* OUT: Columns for imposter table */ 1038 + char **pzImposterPk, /* OUT: Imposter PK clause */ 1039 + char **pzWhere, /* OUT: WHERE clause */ 1040 + int *pnBind /* OUT: Total number of columns */ 1041 +){ 1042 + int rc = p->rc; /* Error code */ 1043 + int rc2; /* sqlite3_finalize() return code */ 1044 + char *zRet = 0; /* String to return */ 1045 + char *zImpCols = 0; /* String to return via *pzImposterCols */ 1046 + char *zImpPK = 0; /* String to return via *pzImposterPK */ 1047 + char *zWhere = 0; /* String to return via *pzWhere */ 1048 + int nBind = 0; /* Value to return via *pnBind */ 1049 + const char *zCom = ""; /* Set to ", " later on */ 1050 + const char *zAnd = ""; /* Set to " AND " later on */ 1051 + sqlite3_stmt *pXInfo = 0; /* PRAGMA index_xinfo = ? */ 1052 + 1053 + if( rc==SQLITE_OK ){ 1054 + assert( p->zErrmsg==0 ); 1055 + rc = prepareFreeAndCollectError(p->dbMain, &pXInfo, &p->zErrmsg, 1056 + sqlite3_mprintf("PRAGMA main.index_xinfo = %Q", pIter->zIdx) 1057 + ); 1058 + } 1059 + 1060 + while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pXInfo) ){ 1061 + int iCid = sqlite3_column_int(pXInfo, 1); 1062 + int bDesc = sqlite3_column_int(pXInfo, 3); 1063 + const char *zCollate = (const char*)sqlite3_column_text(pXInfo, 4); 1064 + const char *zCol; 1065 + const char *zType; 1066 + 1067 + if( iCid<0 ){ 1068 + /* An integer primary key. If the table has an explicit IPK, use 1069 + ** its name. Otherwise, use "ota_rowid". */ 1070 + if( pIter->eType==OTA_PK_IPK ){ 1071 + int i; 1072 + for(i=0; pIter->abTblPk[i]==0; i++); 1073 + assert( i<pIter->nTblCol ); 1074 + zCol = pIter->azTblCol[i]; 1075 + }else{ 1076 + zCol = "ota_rowid"; 1077 + } 1078 + zType = "INTEGER"; 1079 + }else{ 1080 + zCol = pIter->azTblCol[iCid]; 1081 + zType = pIter->azTblType[iCid]; 1082 + } 1083 + 1084 + zRet = sqlite3_mprintf("%z%s\"%w\" COLLATE %Q", zRet, zCom, zCol, zCollate); 1085 + if( pIter->bUnique==0 || sqlite3_column_int(pXInfo, 5) ){ 1086 + const char *zOrder = (bDesc ? " DESC" : ""); 1087 + zImpPK = sqlite3_mprintf("%z%s\"ota_imp_%d%w\"%s", 1088 + zImpPK, zCom, nBind, zCol, zOrder 1089 + ); 1090 + } 1091 + zImpCols = sqlite3_mprintf("%z%s\"ota_imp_%d%w\" %s COLLATE %Q", 1092 + zImpCols, zCom, nBind, zCol, zType, zCollate 1093 + ); 1094 + zWhere = sqlite3_mprintf( 1095 + "%z%s\"ota_imp_%d%w\" IS ?", zWhere, zAnd, nBind, zCol 1096 + ); 1097 + if( zRet==0 || zImpPK==0 || zImpCols==0 || zWhere==0 ) rc = SQLITE_NOMEM; 1098 + zCom = ", "; 1099 + zAnd = " AND "; 1100 + nBind++; 1101 + } 1102 + 1103 + rc2 = sqlite3_finalize(pXInfo); 1104 + if( rc==SQLITE_OK ) rc = rc2; 1105 + 1106 + if( rc!=SQLITE_OK ){ 1107 + sqlite3_free(zRet); 1108 + sqlite3_free(zImpCols); 1109 + sqlite3_free(zImpPK); 1110 + sqlite3_free(zWhere); 1111 + zRet = 0; 1112 + zImpCols = 0; 1113 + zImpPK = 0; 1114 + zWhere = 0; 1115 + p->rc = rc; 1116 + } 1117 + 1118 + *pzImposterCols = zImpCols; 1119 + *pzImposterPk = zImpPK; 1120 + *pzWhere = zWhere; 1121 + *pnBind = nBind; 1122 + return zRet; 1123 +} 1124 + 1125 +/* 1126 +** Assuming the current table columns are "a", "b" and "c", and the zObj 1127 +** paramter is passed "old", return a string of the form: 1128 +** 1129 +** "old.a, old.b, old.b" 1130 +** 1131 +** With the column names escaped. 1132 +** 1133 +** For tables with implicit rowids - OTA_PK_EXTERNAL and OTA_PK_NONE, append 1134 +** the text ", old._rowid_" to the returned value. 1135 +*/ 1136 +static char *otaObjIterGetOldlist( 1137 + sqlite3ota *p, 1138 + OtaObjIter *pIter, 1139 + const char *zObj 1140 +){ 1141 + char *zList = 0; 1142 + if( p->rc==SQLITE_OK && pIter->abIndexed ){ 1143 + const char *zS = ""; 1144 + int i; 1145 + for(i=0; i<pIter->nTblCol; i++){ 1146 + if( pIter->abIndexed[i] ){ 1147 + const char *zCol = pIter->azTblCol[i]; 1148 + zList = sqlite3_mprintf("%z%s%s.\"%w\"", zList, zS, zObj, zCol); 1149 + }else{ 1150 + zList = sqlite3_mprintf("%z%sNULL", zList, zS); 1151 + } 1152 + zS = ", "; 1153 + if( zList==0 ){ 1154 + p->rc = SQLITE_NOMEM; 1155 + break; 1156 + } 1157 + } 1158 + 1159 + /* For a table with implicit rowids, append "old._rowid_" to the list. */ 1160 + if( pIter->eType==OTA_PK_EXTERNAL || pIter->eType==OTA_PK_NONE ){ 1161 + zList = otaMPrintf(p, "%z, %s._rowid_", zList, zObj); 1162 + } 1163 + } 1164 + return zList; 1165 +} 1166 + 1167 +/* 1168 +** Return an expression that can be used in a WHERE clause to match the 1169 +** primary key of the current table. For example, if the table is: 1170 +** 1171 +** CREATE TABLE t1(a, b, c, PRIMARY KEY(b, c)); 1172 +** 1173 +** Return the string: 1174 +** 1175 +** "b = ?1 AND c = ?2" 1176 +*/ 1177 +static char *otaObjIterGetWhere( 1178 + sqlite3ota *p, 1179 + OtaObjIter *pIter 1180 +){ 1181 + char *zList = 0; 1182 + if( pIter->eType==OTA_PK_VTAB || pIter->eType==OTA_PK_NONE ){ 1183 + zList = otaMPrintf(p, "_rowid_ = ?%d", pIter->nTblCol+1); 1184 + }else if( pIter->eType==OTA_PK_EXTERNAL ){ 1185 + const char *zSep = ""; 1186 + int i; 1187 + for(i=0; i<pIter->nTblCol; i++){ 1188 + if( pIter->abTblPk[i] ){ 1189 + zList = otaMPrintf(p, "%z%sc%d=?%d", zList, zSep, i, i+1); 1190 + zSep = " AND "; 1191 + } 1192 + } 1193 + zList = otaMPrintf(p, 1194 + "_rowid_ = (SELECT id FROM ota_imposter2 WHERE %z)", zList 1195 + ); 1196 + 1197 + }else{ 1198 + const char *zSep = ""; 1199 + int i; 1200 + for(i=0; i<pIter->nTblCol; i++){ 1201 + if( pIter->abTblPk[i] ){ 1202 + const char *zCol = pIter->azTblCol[i]; 1203 + zList = otaMPrintf(p, "%z%s\"%w\"=?%d", zList, zSep, zCol, i+1); 1204 + zSep = " AND "; 1205 + } 1206 + } 1207 + } 1208 + return zList; 1209 +} 1210 + 1211 +/* 1212 +** The SELECT statement iterating through the keys for the current object 1213 +** (p->objiter.pSelect) currently points to a valid row. However, there 1214 +** is something wrong with the ota_control value in the ota_control value 1215 +** stored in the (p->nCol+1)'th column. Set the error code and error message 1216 +** of the OTA handle to something reflecting this. 1217 +*/ 1218 +static void otaBadControlError(sqlite3ota *p){ 1219 + p->rc = SQLITE_ERROR; 1220 + p->zErrmsg = sqlite3_mprintf("invalid ota_control value"); 1221 +} 1222 + 1223 + 1224 +/* 1225 +** Return a nul-terminated string containing the comma separated list of 1226 +** assignments that should be included following the "SET" keyword of 1227 +** an UPDATE statement used to update the table object that the iterator 1228 +** passed as the second argument currently points to if the ota_control 1229 +** column of the data_xxx table entry is set to zMask. 1230 +** 1231 +** The memory for the returned string is obtained from sqlite3_malloc(). 1232 +** It is the responsibility of the caller to eventually free it using 1233 +** sqlite3_free(). 1234 +** 1235 +** If an OOM error is encountered when allocating space for the new 1236 +** string, an error code is left in the ota handle passed as the first 1237 +** argument and NULL is returned. Or, if an error has already occurred 1238 +** when this function is called, NULL is returned immediately, without 1239 +** attempting the allocation or modifying the stored error code. 1240 +*/ 1241 +static char *otaObjIterGetSetlist( 1242 + sqlite3ota *p, 1243 + OtaObjIter *pIter, 1244 + const char *zMask 1245 +){ 1246 + char *zList = 0; 1247 + if( p->rc==SQLITE_OK ){ 1248 + int i; 1249 + 1250 + if( strlen(zMask)!=pIter->nTblCol ){ 1251 + otaBadControlError(p); 1252 + }else{ 1253 + const char *zSep = ""; 1254 + for(i=0; i<pIter->nTblCol; i++){ 1255 + char c = zMask[pIter->aiSrcOrder[i]]; 1256 + if( c=='x' ){ 1257 + zList = otaMPrintf(p, "%z%s\"%w\"=?%d", 1258 + zList, zSep, pIter->azTblCol[i], i+1 1259 + ); 1260 + zSep = ", "; 1261 + } 1262 + if( c=='d' ){ 1263 + zList = otaMPrintf(p, "%z%s\"%w\"=ota_delta(\"%w\", ?%d)", 1264 + zList, zSep, pIter->azTblCol[i], pIter->azTblCol[i], i+1 1265 + ); 1266 + zSep = ", "; 1267 + } 1268 + } 1269 + } 1270 + } 1271 + return zList; 1272 +} 1273 + 1274 +/* 1275 +** Return a nul-terminated string consisting of nByte comma separated 1276 +** "?" expressions. For example, if nByte is 3, return a pointer to 1277 +** a buffer containing the string "?,?,?". 1278 +** 1279 +** The memory for the returned string is obtained from sqlite3_malloc(). 1280 +** It is the responsibility of the caller to eventually free it using 1281 +** sqlite3_free(). 1282 +** 1283 +** If an OOM error is encountered when allocating space for the new 1284 +** string, an error code is left in the ota handle passed as the first 1285 +** argument and NULL is returned. Or, if an error has already occurred 1286 +** when this function is called, NULL is returned immediately, without 1287 +** attempting the allocation or modifying the stored error code. 1288 +*/ 1289 +static char *otaObjIterGetBindlist(sqlite3ota *p, int nBind){ 1290 + char *zRet = 0; 1291 + int nByte = nBind*2 + 1; 1292 + 1293 + zRet = (char*)otaMalloc(p, nByte); 1294 + if( zRet ){ 1295 + int i; 1296 + for(i=0; i<nBind; i++){ 1297 + zRet[i*2] = '?'; 1298 + zRet[i*2+1] = (i+1==nBind) ? '\0' : ','; 1299 + } 1300 + } 1301 + return zRet; 1302 +} 1303 + 1304 +/* 1305 +** The iterator currently points to a table (not index) of type 1306 +** OTA_PK_WITHOUT_ROWID. This function creates the PRIMARY KEY 1307 +** declaration for the corresponding imposter table. For example, 1308 +** if the iterator points to a table created as: 1309 +** 1310 +** CREATE TABLE t1(a, b, c, PRIMARY KEY(b, a DESC)) WITHOUT ROWID 1311 +** 1312 +** this function returns: 1313 +** 1314 +** PRIMARY KEY("b", "a" DESC) 1315 +*/ 1316 +static char *otaWithoutRowidPK(sqlite3ota *p, OtaObjIter *pIter){ 1317 + char *z = 0; 1318 + assert( pIter->zIdx==0 ); 1319 + if( p->rc==SQLITE_OK ){ 1320 + const char *zSep = "PRIMARY KEY("; 1321 + sqlite3_stmt *pXList = 0; /* PRAGMA index_list = (pIter->zTbl) */ 1322 + sqlite3_stmt *pXInfo = 0; /* PRAGMA index_xinfo = <pk-index> */ 1323 + 1324 + p->rc = prepareFreeAndCollectError(p->dbMain, &pXList, &p->zErrmsg, 1325 + sqlite3_mprintf("PRAGMA main.index_list = %Q", pIter->zTbl) 1326 + ); 1327 + while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pXList) ){ 1328 + const char *zOrig = (const char*)sqlite3_column_text(pXList,3); 1329 + if( zOrig && strcmp(zOrig, "pk")==0 ){ 1330 + const char *zIdx = (const char*)sqlite3_column_text(pXList,1); 1331 + if( zIdx ){ 1332 + p->rc = prepareFreeAndCollectError(p->dbMain, &pXInfo, &p->zErrmsg, 1333 + sqlite3_mprintf("PRAGMA main.index_xinfo = %Q", zIdx) 1334 + ); 1335 + } 1336 + break; 1337 + } 1338 + } 1339 + otaFinalize(p, pXList); 1340 + 1341 + while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pXInfo) ){ 1342 + if( sqlite3_column_int(pXInfo, 5) ){ 1343 + /* int iCid = sqlite3_column_int(pXInfo, 0); */ 1344 + const char *zCol = (const char*)sqlite3_column_text(pXInfo, 2); 1345 + const char *zDesc = sqlite3_column_int(pXInfo, 3) ? " DESC" : ""; 1346 + z = otaMPrintf(p, "%z%s\"%w\"%s", z, zSep, zCol, zDesc); 1347 + zSep = ", "; 1348 + } 1349 + } 1350 + z = otaMPrintf(p, "%z)", z); 1351 + otaFinalize(p, pXInfo); 1352 + } 1353 + return z; 1354 +} 1355 + 1356 +/* 1357 +** This function creates the second imposter table used when writing to 1358 +** a table b-tree where the table has an external primary key. If the 1359 +** iterator passed as the second argument does not currently point to 1360 +** a table (not index) with an external primary key, this function is a 1361 +** no-op. 1362 +** 1363 +** Assuming the iterator does point to a table with an external PK, this 1364 +** function creates a WITHOUT ROWID imposter table named "ota_imposter2" 1365 +** used to access that PK index. For example, if the target table is 1366 +** declared as follows: 1367 +** 1368 +** CREATE TABLE t1(a, b TEXT, c REAL, PRIMARY KEY(b, c)); 1369 +** 1370 +** then the imposter table schema is: 1371 +** 1372 +** CREATE TABLE ota_imposter2(c1 TEXT, c2 REAL, id INTEGER) WITHOUT ROWID; 1373 +** 1374 +*/ 1375 +static void otaCreateImposterTable2(sqlite3ota *p, OtaObjIter *pIter){ 1376 + if( p->rc==SQLITE_OK && pIter->eType==OTA_PK_EXTERNAL ){ 1377 + int tnum = pIter->iPkTnum; /* Root page of PK index */ 1378 + sqlite3_stmt *pQuery = 0; /* SELECT name ... WHERE rootpage = $tnum */ 1379 + const char *zIdx = 0; /* Name of PK index */ 1380 + sqlite3_stmt *pXInfo = 0; /* PRAGMA main.index_xinfo = $zIdx */ 1381 + const char *zComma = ""; 1382 + char *zCols = 0; /* Used to build up list of table cols */ 1383 + char *zPk = 0; /* Used to build up table PK declaration */ 1384 + 1385 + /* Figure out the name of the primary key index for the current table. 1386 + ** This is needed for the argument to "PRAGMA index_xinfo". Set 1387 + ** zIdx to point to a nul-terminated string containing this name. */ 1388 + p->rc = prepareAndCollectError(p->dbMain, &pQuery, &p->zErrmsg, 1389 + "SELECT name FROM sqlite_master WHERE rootpage = ?" 1390 + ); 1391 + if( p->rc==SQLITE_OK ){ 1392 + sqlite3_bind_int(pQuery, 1, tnum); 1393 + if( SQLITE_ROW==sqlite3_step(pQuery) ){ 1394 + zIdx = (const char*)sqlite3_column_text(pQuery, 0); 1395 + } 1396 + } 1397 + if( zIdx ){ 1398 + p->rc = prepareFreeAndCollectError(p->dbMain, &pXInfo, &p->zErrmsg, 1399 + sqlite3_mprintf("PRAGMA main.index_xinfo = %Q", zIdx) 1400 + ); 1401 + } 1402 + otaFinalize(p, pQuery); 1403 + 1404 + while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pXInfo) ){ 1405 + int bKey = sqlite3_column_int(pXInfo, 5); 1406 + if( bKey ){ 1407 + int iCid = sqlite3_column_int(pXInfo, 1); 1408 + int bDesc = sqlite3_column_int(pXInfo, 3); 1409 + const char *zCollate = (const char*)sqlite3_column_text(pXInfo, 4); 1410 + zCols = otaMPrintf(p, "%z%sc%d %s COLLATE %s", zCols, zComma, 1411 + iCid, pIter->azTblType[iCid], zCollate 1412 + ); 1413 + zPk = otaMPrintf(p, "%z%sc%d%s", zPk, zComma, iCid, bDesc?" DESC":""); 1414 + zComma = ", "; 1415 + } 1416 + } 1417 + zCols = otaMPrintf(p, "%z, id INTEGER", zCols); 1418 + otaFinalize(p, pXInfo); 1419 + 1420 + sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->dbMain, "main", 1, tnum); 1421 + otaMPrintfExec(p, p->dbMain, 1422 + "CREATE TABLE ota_imposter2(%z, PRIMARY KEY(%z)) WITHOUT ROWID", 1423 + zCols, zPk 1424 + ); 1425 + sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->dbMain, "main", 0, 0); 1426 + } 1427 +} 1428 + 1429 +/* 1430 +** If an error has already occurred when this function is called, it 1431 +** immediately returns zero (without doing any work). Or, if an error 1432 +** occurs during the execution of this function, it sets the error code 1433 +** in the sqlite3ota object indicated by the first argument and returns 1434 +** zero. 1435 +** 1436 +** The iterator passed as the second argument is guaranteed to point to 1437 +** a table (not an index) when this function is called. This function 1438 +** attempts to create any imposter table required to write to the main 1439 +** table b-tree of the table before returning. Non-zero is returned if 1440 +** an imposter table are created, or zero otherwise. 1441 +** 1442 +** An imposter table is required in all cases except OTA_PK_VTAB. Only 1443 +** virtual tables are written to directly. The imposter table has the 1444 +** same schema as the actual target table (less any UNIQUE constraints). 1445 +** More precisely, the "same schema" means the same columns, types, 1446 +** collation sequences. For tables that do not have an external PRIMARY 1447 +** KEY, it also means the same PRIMARY KEY declaration. 1448 +*/ 1449 +static void otaCreateImposterTable(sqlite3ota *p, OtaObjIter *pIter){ 1450 + if( p->rc==SQLITE_OK && pIter->eType!=OTA_PK_VTAB ){ 1451 + int tnum = pIter->iTnum; 1452 + const char *zComma = ""; 1453 + char *zSql = 0; 1454 + int iCol; 1455 + sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->dbMain, "main", 0, 1); 1456 + 1457 + for(iCol=0; p->rc==SQLITE_OK && iCol<pIter->nTblCol; iCol++){ 1458 + const char *zPk = ""; 1459 + const char *zCol = pIter->azTblCol[iCol]; 1460 + const char *zColl = 0; 1461 + 1462 + p->rc = sqlite3_table_column_metadata( 1463 + p->dbMain, "main", pIter->zTbl, zCol, 0, &zColl, 0, 0, 0 1464 + ); 1465 + 1466 + if( pIter->eType==OTA_PK_IPK && pIter->abTblPk[iCol] ){ 1467 + /* If the target table column is an "INTEGER PRIMARY KEY", add 1468 + ** "PRIMARY KEY" to the imposter table column declaration. */ 1469 + zPk = "PRIMARY KEY "; 1470 + } 1471 + zSql = otaMPrintf(p, "%z%s\"%w\" %s %sCOLLATE %s%s", 1472 + zSql, zComma, zCol, pIter->azTblType[iCol], zPk, zColl, 1473 + (pIter->abNotNull[iCol] ? " NOT NULL" : "") 1474 + ); 1475 + zComma = ", "; 1476 + } 1477 + 1478 + if( pIter->eType==OTA_PK_WITHOUT_ROWID ){ 1479 + char *zPk = otaWithoutRowidPK(p, pIter); 1480 + if( zPk ){ 1481 + zSql = otaMPrintf(p, "%z, %z", zSql, zPk); 1482 + } 1483 + } 1484 + 1485 + sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->dbMain, "main", 1, tnum); 1486 + otaMPrintfExec(p, p->dbMain, "CREATE TABLE \"ota_imp_%w\"(%z)%s", 1487 + pIter->zTbl, zSql, 1488 + (pIter->eType==OTA_PK_WITHOUT_ROWID ? " WITHOUT ROWID" : "") 1489 + ); 1490 + sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->dbMain, "main", 0, 0); 1491 + } 1492 +} 1493 + 1494 +/* 1495 +** Prepare a statement used to insert rows into the "ota_tmp_xxx" table. 1496 +** Specifically a statement of the form: 1497 +** 1498 +** INSERT INTO ota_tmp_xxx VALUES(?, ?, ? ...); 1499 +** 1500 +** The number of bound variables is equal to the number of columns in 1501 +** the target table, plus one (for the ota_control column), plus one more 1502 +** (for the ota_rowid column) if the target table is an implicit IPK or 1503 +** virtual table. 1504 +*/ 1505 +static void otaObjIterPrepareTmpInsert( 1506 + sqlite3ota *p, 1507 + OtaObjIter *pIter, 1508 + const char *zCollist, 1509 + const char *zOtaRowid 1510 +){ 1511 + int bOtaRowid = (pIter->eType==OTA_PK_EXTERNAL || pIter->eType==OTA_PK_NONE); 1512 + char *zBind = otaObjIterGetBindlist(p, pIter->nTblCol + 1 + bOtaRowid); 1513 + if( zBind ){ 1514 + assert( pIter->pTmpInsert==0 ); 1515 + p->rc = prepareFreeAndCollectError( 1516 + p->dbOta, &pIter->pTmpInsert, &p->zErrmsg, sqlite3_mprintf( 1517 + "INSERT INTO %s.'ota_tmp_%q'(ota_control,%s%s) VALUES(%z)", 1518 + p->zStateDb, pIter->zTbl, zCollist, zOtaRowid, zBind 1519 + )); 1520 + } 1521 +} 1522 + 1523 +static void otaTmpInsertFunc( 1524 + sqlite3_context *pCtx, 1525 + int nVal, 1526 + sqlite3_value **apVal 1527 +){ 1528 + sqlite3ota *p = sqlite3_user_data(pCtx); 1529 + int rc = SQLITE_OK; 1530 + int i; 1531 + 1532 + for(i=0; rc==SQLITE_OK && i<nVal; i++){ 1533 + rc = sqlite3_bind_value(p->objiter.pTmpInsert, i+1, apVal[i]); 1534 + } 1535 + if( rc==SQLITE_OK ){ 1536 + sqlite3_step(p->objiter.pTmpInsert); 1537 + rc = sqlite3_reset(p->objiter.pTmpInsert); 1538 + } 1539 + 1540 + if( rc!=SQLITE_OK ){ 1541 + sqlite3_result_error_code(pCtx, rc); 1542 + } 1543 +} 1544 + 1545 +/* 1546 +** Ensure that the SQLite statement handles required to update the 1547 +** target database object currently indicated by the iterator passed 1548 +** as the second argument are available. 1549 +*/ 1550 +static int otaObjIterPrepareAll( 1551 + sqlite3ota *p, 1552 + OtaObjIter *pIter, 1553 + int nOffset /* Add "LIMIT -1 OFFSET $nOffset" to SELECT */ 1554 +){ 1555 + assert( pIter->bCleanup==0 ); 1556 + if( pIter->pSelect==0 && otaObjIterCacheTableInfo(p, pIter)==SQLITE_OK ){ 1557 + const int tnum = pIter->iTnum; 1558 + char *zCollist = 0; /* List of indexed columns */ 1559 + char **pz = &p->zErrmsg; 1560 + const char *zIdx = pIter->zIdx; 1561 + char *zLimit = 0; 1562 + 1563 + if( nOffset ){ 1564 + zLimit = sqlite3_mprintf(" LIMIT -1 OFFSET %d", nOffset); 1565 + if( !zLimit ) p->rc = SQLITE_NOMEM; 1566 + } 1567 + 1568 + if( zIdx ){ 1569 + const char *zTbl = pIter->zTbl; 1570 + char *zImposterCols = 0; /* Columns for imposter table */ 1571 + char *zImposterPK = 0; /* Primary key declaration for imposter */ 1572 + char *zWhere = 0; /* WHERE clause on PK columns */ 1573 + char *zBind = 0; 1574 + int nBind = 0; 1575 + 1576 + assert( pIter->eType!=OTA_PK_VTAB ); 1577 + zCollist = otaObjIterGetIndexCols( 1578 + p, pIter, &zImposterCols, &zImposterPK, &zWhere, &nBind 1579 + ); 1580 + zBind = otaObjIterGetBindlist(p, nBind); 1581 + 1582 + /* Create the imposter table used to write to this index. */ 1583 + sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->dbMain, "main", 0, 1); 1584 + sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->dbMain, "main", 1,tnum); 1585 + otaMPrintfExec(p, p->dbMain, 1586 + "CREATE TABLE \"ota_imp_%w\"( %s, PRIMARY KEY( %s ) ) WITHOUT ROWID", 1587 + zTbl, zImposterCols, zImposterPK 1588 + ); 1589 + sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->dbMain, "main", 0, 0); 1590 + 1591 + /* Create the statement to insert index entries */ 1592 + pIter->nCol = nBind; 1593 + if( p->rc==SQLITE_OK ){ 1594 + p->rc = prepareFreeAndCollectError( 1595 + p->dbMain, &pIter->pInsert, &p->zErrmsg, 1596 + sqlite3_mprintf("INSERT INTO \"ota_imp_%w\" VALUES(%s)", zTbl, zBind) 1597 + ); 1598 + } 1599 + 1600 + /* And to delete index entries */ 1601 + if( p->rc==SQLITE_OK ){ 1602 + p->rc = prepareFreeAndCollectError( 1603 + p->dbMain, &pIter->pDelete, &p->zErrmsg, 1604 + sqlite3_mprintf("DELETE FROM \"ota_imp_%w\" WHERE %s", zTbl, zWhere) 1605 + ); 1606 + } 1607 + 1608 + /* Create the SELECT statement to read keys in sorted order */ 1609 + if( p->rc==SQLITE_OK ){ 1610 + char *zSql; 1611 + if( pIter->eType==OTA_PK_EXTERNAL || pIter->eType==OTA_PK_NONE ){ 1612 + zSql = sqlite3_mprintf( 1613 + "SELECT %s, ota_control FROM %s.'ota_tmp_%q' ORDER BY %s%s", 1614 + zCollist, p->zStateDb, pIter->zTbl, 1615 + zCollist, zLimit 1616 + ); 1617 + }else{ 1618 + zSql = sqlite3_mprintf( 1619 + "SELECT %s, ota_control FROM 'data_%q' " 1620 + "WHERE typeof(ota_control)='integer' AND ota_control!=1 " 1621 + "UNION ALL " 1622 + "SELECT %s, ota_control FROM %s.'ota_tmp_%q' " 1623 + "ORDER BY %s%s", 1624 + zCollist, pIter->zTbl, 1625 + zCollist, p->zStateDb, pIter->zTbl, 1626 + zCollist, zLimit 1627 + ); 1628 + } 1629 + p->rc = prepareFreeAndCollectError(p->dbOta, &pIter->pSelect, pz, zSql); 1630 + } 1631 + 1632 + sqlite3_free(zImposterCols); 1633 + sqlite3_free(zImposterPK); 1634 + sqlite3_free(zWhere); 1635 + sqlite3_free(zBind); 1636 + }else{ 1637 + int bOtaRowid = (pIter->eType==OTA_PK_VTAB || pIter->eType==OTA_PK_NONE); 1638 + const char *zTbl = pIter->zTbl; /* Table this step applies to */ 1639 + const char *zWrite; /* Imposter table name */ 1640 + 1641 + char *zBindings = otaObjIterGetBindlist(p, pIter->nTblCol + bOtaRowid); 1642 + char *zWhere = otaObjIterGetWhere(p, pIter); 1643 + char *zOldlist = otaObjIterGetOldlist(p, pIter, "old"); 1644 + char *zNewlist = otaObjIterGetOldlist(p, pIter, "new"); 1645 + 1646 + zCollist = otaObjIterGetCollist(p, pIter); 1647 + pIter->nCol = pIter->nTblCol; 1648 + 1649 + /* Create the SELECT statement to read keys from data_xxx */ 1650 + if( p->rc==SQLITE_OK ){ 1651 + p->rc = prepareFreeAndCollectError(p->dbOta, &pIter->pSelect, pz, 1652 + sqlite3_mprintf( 1653 + "SELECT %s, ota_control%s FROM 'data_%q'%s", 1654 + zCollist, (bOtaRowid ? ", ota_rowid" : ""), zTbl, zLimit 1655 + ) 1656 + ); 1657 + } 1658 + 1659 + /* Create the imposter table or tables (if required). */ 1660 + otaCreateImposterTable(p, pIter); 1661 + otaCreateImposterTable2(p, pIter); 1662 + zWrite = (pIter->eType==OTA_PK_VTAB ? "" : "ota_imp_"); 1663 + 1664 + /* Create the INSERT statement to write to the target PK b-tree */ 1665 + if( p->rc==SQLITE_OK ){ 1666 + p->rc = prepareFreeAndCollectError(p->dbMain, &pIter->pInsert, pz, 1667 + sqlite3_mprintf( 1668 + "INSERT INTO \"%s%w\"(%s%s) VALUES(%s)", 1669 + zWrite, zTbl, zCollist, (bOtaRowid ? ", _rowid_" : ""), zBindings 1670 + ) 1671 + ); 1672 + } 1673 + 1674 + /* Create the DELETE statement to write to the target PK b-tree */ 1675 + if( p->rc==SQLITE_OK ){ 1676 + p->rc = prepareFreeAndCollectError(p->dbMain, &pIter->pDelete, pz, 1677 + sqlite3_mprintf( 1678 + "DELETE FROM \"%s%w\" WHERE %s", zWrite, zTbl, zWhere 1679 + ) 1680 + ); 1681 + } 1682 + 1683 + if( pIter->abIndexed ){ 1684 + const char *zOtaRowid = ""; 1685 + if( pIter->eType==OTA_PK_EXTERNAL || pIter->eType==OTA_PK_NONE ){ 1686 + zOtaRowid = ", ota_rowid"; 1687 + } 1688 + 1689 + /* Create the ota_tmp_xxx table and the triggers to populate it. */ 1690 + otaMPrintfExec(p, p->dbOta, 1691 + "CREATE TABLE IF NOT EXISTS %s.'ota_tmp_%q' AS " 1692 + "SELECT *%s FROM 'data_%q' WHERE 0;" 1693 + , p->zStateDb 1694 + , zTbl, (pIter->eType==OTA_PK_EXTERNAL ? ", 0 AS ota_rowid" : "") 1695 + , zTbl 1696 + ); 1697 + 1698 + otaMPrintfExec(p, p->dbMain, 1699 + "CREATE TEMP TRIGGER ota_delete_tr BEFORE DELETE ON \"%s%w\" " 1700 + "BEGIN " 1701 + " SELECT ota_tmp_insert(2, %s);" 1702 + "END;" 1703 + 1704 + "CREATE TEMP TRIGGER ota_update1_tr BEFORE UPDATE ON \"%s%w\" " 1705 + "BEGIN " 1706 + " SELECT ota_tmp_insert(2, %s);" 1707 + "END;" 1708 + 1709 + "CREATE TEMP TRIGGER ota_update2_tr AFTER UPDATE ON \"%s%w\" " 1710 + "BEGIN " 1711 + " SELECT ota_tmp_insert(3, %s);" 1712 + "END;", 1713 + zWrite, zTbl, zOldlist, 1714 + zWrite, zTbl, zOldlist, 1715 + zWrite, zTbl, zNewlist 1716 + ); 1717 + 1718 + if( pIter->eType==OTA_PK_EXTERNAL || pIter->eType==OTA_PK_NONE ){ 1719 + otaMPrintfExec(p, p->dbMain, 1720 + "CREATE TEMP TRIGGER ota_insert_tr AFTER INSERT ON \"%s%w\" " 1721 + "BEGIN " 1722 + " SELECT ota_tmp_insert(0, %s);" 1723 + "END;", 1724 + zWrite, zTbl, zNewlist 1725 + ); 1726 + } 1727 + 1728 + otaObjIterPrepareTmpInsert(p, pIter, zCollist, zOtaRowid); 1729 + } 1730 + 1731 + sqlite3_free(zWhere); 1732 + sqlite3_free(zOldlist); 1733 + sqlite3_free(zNewlist); 1734 + sqlite3_free(zBindings); 1735 + } 1736 + sqlite3_free(zCollist); 1737 + sqlite3_free(zLimit); 1738 + } 1739 + 1740 + return p->rc; 1741 +} 1742 + 1743 +/* 1744 +** Set output variable *ppStmt to point to an UPDATE statement that may 1745 +** be used to update the imposter table for the main table b-tree of the 1746 +** table object that pIter currently points to, assuming that the 1747 +** ota_control column of the data_xyz table contains zMask. 1748 +** 1749 +** If the zMask string does not specify any columns to update, then this 1750 +** is not an error. Output variable *ppStmt is set to NULL in this case. 1751 +*/ 1752 +static int otaGetUpdateStmt( 1753 + sqlite3ota *p, /* OTA handle */ 1754 + OtaObjIter *pIter, /* Object iterator */ 1755 + const char *zMask, /* ota_control value ('x.x.') */ 1756 + sqlite3_stmt **ppStmt /* OUT: UPDATE statement handle */ 1757 +){ 1758 + OtaUpdateStmt **pp; 1759 + OtaUpdateStmt *pUp = 0; 1760 + int nUp = 0; 1761 + 1762 + /* In case an error occurs */ 1763 + *ppStmt = 0; 1764 + 1765 + /* Search for an existing statement. If one is found, shift it to the front 1766 + ** of the LRU queue and return immediately. Otherwise, leave nUp pointing 1767 + ** to the number of statements currently in the cache and pUp to the 1768 + ** last object in the list. */ 1769 + for(pp=&pIter->pOtaUpdate; *pp; pp=&((*pp)->pNext)){ 1770 + pUp = *pp; 1771 + if( strcmp(pUp->zMask, zMask)==0 ){ 1772 + *pp = pUp->pNext; 1773 + pUp->pNext = pIter->pOtaUpdate; 1774 + pIter->pOtaUpdate = pUp; 1775 + *ppStmt = pUp->pUpdate; 1776 + return SQLITE_OK; 1777 + } 1778 + nUp++; 1779 + } 1780 + assert( pUp==0 || pUp->pNext==0 ); 1781 + 1782 + if( nUp>=SQLITE_OTA_UPDATE_CACHESIZE ){ 1783 + for(pp=&pIter->pOtaUpdate; *pp!=pUp; pp=&((*pp)->pNext)); 1784 + *pp = 0; 1785 + sqlite3_finalize(pUp->pUpdate); 1786 + pUp->pUpdate = 0; 1787 + }else{ 1788 + pUp = (OtaUpdateStmt*)otaMalloc(p, sizeof(OtaUpdateStmt)+pIter->nTblCol+1); 1789 + } 1790 + 1791 + if( pUp ){ 1792 + char *zWhere = otaObjIterGetWhere(p, pIter); 1793 + char *zSet = otaObjIterGetSetlist(p, pIter, zMask); 1794 + char *zUpdate = 0; 1795 + 1796 + pUp->zMask = (char*)&pUp[1]; 1797 + memcpy(pUp->zMask, zMask, pIter->nTblCol); 1798 + pUp->pNext = pIter->pOtaUpdate; 1799 + pIter->pOtaUpdate = pUp; 1800 + 1801 + if( zSet ){ 1802 + const char *zPrefix = ""; 1803 + 1804 + if( pIter->eType!=OTA_PK_VTAB ) zPrefix = "ota_imp_"; 1805 + zUpdate = sqlite3_mprintf("UPDATE \"%s%w\" SET %s WHERE %s", 1806 + zPrefix, pIter->zTbl, zSet, zWhere 1807 + ); 1808 + p->rc = prepareFreeAndCollectError( 1809 + p->dbMain, &pUp->pUpdate, &p->zErrmsg, zUpdate 1810 + ); 1811 + *ppStmt = pUp->pUpdate; 1812 + } 1813 + sqlite3_free(zWhere); 1814 + sqlite3_free(zSet); 1815 + } 1816 + 1817 + return p->rc; 1818 +} 1819 + 1820 +static sqlite3 *otaOpenDbhandle(sqlite3ota *p, const char *zName){ 1821 + sqlite3 *db = 0; 1822 + if( p->rc==SQLITE_OK ){ 1823 + const int flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_URI; 1824 + p->rc = sqlite3_open_v2(zName, &db, flags, p->zVfsName); 1825 + if( p->rc ){ 1826 + p->zErrmsg = sqlite3_mprintf("%s", sqlite3_errmsg(db)); 1827 + sqlite3_close(db); 1828 + db = 0; 1829 + } 1830 + } 1831 + return db; 1832 +} 1833 + 1834 +/* 1835 +** Open the database handle and attach the OTA database as "ota". If an 1836 +** error occurs, leave an error code and message in the OTA handle. 1837 +*/ 1838 +static void otaOpenDatabase(sqlite3ota *p){ 1839 + assert( p->rc==SQLITE_OK ); 1840 + assert( p->dbMain==0 && p->dbOta==0 ); 1841 + 1842 + p->eStage = 0; 1843 + p->dbMain = otaOpenDbhandle(p, p->zTarget); 1844 + p->dbOta = otaOpenDbhandle(p, p->zOta); 1845 + 1846 + /* If using separate OTA and state databases, attach the state database to 1847 + ** the OTA db handle now. */ 1848 + if( p->zState ){ 1849 + otaMPrintfExec(p, p->dbOta, "ATTACH %Q AS stat", p->zState); 1850 + memcpy(p->zStateDb, "stat", 4); 1851 + }else{ 1852 + memcpy(p->zStateDb, "main", 4); 1853 + } 1854 + 1855 + if( p->rc==SQLITE_OK ){ 1856 + p->rc = sqlite3_create_function(p->dbMain, 1857 + "ota_tmp_insert", -1, SQLITE_UTF8, (void*)p, otaTmpInsertFunc, 0, 0 1858 + ); 1859 + } 1860 + 1861 + if( p->rc==SQLITE_OK ){ 1862 + p->rc = sqlite3_file_control(p->dbMain, "main", SQLITE_FCNTL_OTA, (void*)p); 1863 + } 1864 + otaMPrintfExec(p, p->dbMain, "SELECT * FROM sqlite_master"); 1865 + 1866 + /* Mark the database file just opened as an OTA target database. If 1867 + ** this call returns SQLITE_NOTFOUND, then the OTA vfs is not in use. 1868 + ** This is an error. */ 1869 + if( p->rc==SQLITE_OK ){ 1870 + p->rc = sqlite3_file_control(p->dbMain, "main", SQLITE_FCNTL_OTA, (void*)p); 1871 + } 1872 + 1873 + if( p->rc==SQLITE_NOTFOUND ){ 1874 + p->rc = SQLITE_ERROR; 1875 + p->zErrmsg = sqlite3_mprintf("ota vfs not found"); 1876 + } 1877 +} 1878 + 1879 +/* 1880 +** This routine is a copy of the sqlite3FileSuffix3() routine from the core. 1881 +** It is a no-op unless SQLITE_ENABLE_8_3_NAMES is defined. 1882 +** 1883 +** If SQLITE_ENABLE_8_3_NAMES is set at compile-time and if the database 1884 +** filename in zBaseFilename is a URI with the "8_3_names=1" parameter and 1885 +** if filename in z[] has a suffix (a.k.a. "extension") that is longer than 1886 +** three characters, then shorten the suffix on z[] to be the last three 1887 +** characters of the original suffix. 1888 +** 1889 +** If SQLITE_ENABLE_8_3_NAMES is set to 2 at compile-time, then always 1890 +** do the suffix shortening regardless of URI parameter. 1891 +** 1892 +** Examples: 1893 +** 1894 +** test.db-journal => test.nal 1895 +** test.db-wal => test.wal 1896 +** test.db-shm => test.shm 1897 +** test.db-mj7f3319fa => test.9fa 1898 +*/ 1899 +static void otaFileSuffix3(const char *zBase, char *z){ 1900 +#ifdef SQLITE_ENABLE_8_3_NAMES 1901 +#if SQLITE_ENABLE_8_3_NAMES<2 1902 + if( sqlite3_uri_boolean(zBase, "8_3_names", 0) ) 1903 +#endif 1904 + { 1905 + int i, sz; 1906 + sz = sqlite3Strlen30(z); 1907 + for(i=sz-1; i>0 && z[i]!='/' && z[i]!='.'; i--){} 1908 + if( z[i]=='.' && ALWAYS(sz>i+4) ) memmove(&z[i+1], &z[sz-3], 4); 1909 + } 1910 +#endif 1911 +} 1912 + 1913 +/* 1914 +** Return the current wal-index header checksum for the target database 1915 +** as a 64-bit integer. 1916 +** 1917 +** The checksum is store in the first page of xShmMap memory as an 8-byte 1918 +** blob starting at byte offset 40. 1919 +*/ 1920 +static i64 otaShmChecksum(sqlite3ota *p){ 1921 + i64 iRet = 0; 1922 + if( p->rc==SQLITE_OK ){ 1923 + sqlite3_file *pDb = p->pTargetFd->pReal; 1924 + u32 volatile *ptr; 1925 + p->rc = pDb->pMethods->xShmMap(pDb, 0, 32*1024, 0, (void volatile**)&ptr); 1926 + if( p->rc==SQLITE_OK ){ 1927 + iRet = ((i64)ptr[10] << 32) + ptr[11]; 1928 + } 1929 + } 1930 + return iRet; 1931 +} 1932 + 1933 +/* 1934 +** This function is called as part of initializing or reinitializing an 1935 +** incremental checkpoint. 1936 +** 1937 +** It populates the sqlite3ota.aFrame[] array with the set of 1938 +** (wal frame -> db page) copy operations required to checkpoint the 1939 +** current wal file, and obtains the set of shm locks required to safely 1940 +** perform the copy operations directly on the file-system. 1941 +** 1942 +** If argument pState is not NULL, then the incremental checkpoint is 1943 +** being resumed. In this case, if the checksum of the wal-index-header 1944 +** following recovery is not the same as the checksum saved in the OtaState 1945 +** object, then the ota handle is set to DONE state. This occurs if some 1946 +** other client appends a transaction to the wal file in the middle of 1947 +** an incremental checkpoint. 1948 +*/ 1949 +static void otaSetupCheckpoint(sqlite3ota *p, OtaState *pState){ 1950 + 1951 + /* If pState is NULL, then the wal file may not have been opened and 1952 + ** recovered. Running a read-statement here to ensure that doing so 1953 + ** does not interfere with the "capture" process below. */ 1954 + if( pState==0 ){ 1955 + p->eStage = 0; 1956 + if( p->rc==SQLITE_OK ){ 1957 + p->rc = sqlite3_exec(p->dbMain, "SELECT * FROM sqlite_master", 0, 0, 0); 1958 + } 1959 + } 1960 + 1961 + /* Assuming no error has occurred, run a "restart" checkpoint with the 1962 + ** sqlite3ota.eStage variable set to CAPTURE. This turns on the following 1963 + ** special behaviour in the ota VFS: 1964 + ** 1965 + ** * If the exclusive shm WRITER or READ0 lock cannot be obtained, 1966 + ** the checkpoint fails with SQLITE_BUSY (normally SQLite would 1967 + ** proceed with running a passive checkpoint instead of failing). 1968 + ** 1969 + ** * Attempts to read from the *-wal file or write to the database file 1970 + ** do not perform any IO. Instead, the frame/page combinations that 1971 + ** would be read/written are recorded in the sqlite3ota.aFrame[] 1972 + ** array. 1973 + ** 1974 + ** * Calls to xShmLock(UNLOCK) to release the exclusive shm WRITER, 1975 + ** READ0 and CHECKPOINT locks taken as part of the checkpoint are 1976 + ** no-ops. These locks will not be released until the connection 1977 + ** is closed. 1978 + ** 1979 + ** * Attempting to xSync() the database file causes an SQLITE_INTERNAL 1980 + ** error. 1981 + ** 1982 + ** As a result, unless an error (i.e. OOM or SQLITE_BUSY) occurs, the 1983 + ** checkpoint below fails with SQLITE_INTERNAL, and leaves the aFrame[] 1984 + ** array populated with a set of (frame -> page) mappings. Because the 1985 + ** WRITER, CHECKPOINT and READ0 locks are still held, it is safe to copy 1986 + ** data from the wal file into the database file according to the 1987 + ** contents of aFrame[]. 1988 + */ 1989 + if( p->rc==SQLITE_OK ){ 1990 + int rc2; 1991 + p->eStage = OTA_STAGE_CAPTURE; 1992 + rc2 = sqlite3_exec(p->dbMain, "PRAGMA main.wal_checkpoint=restart", 0, 0,0); 1993 + if( rc2!=SQLITE_INTERNAL ) p->rc = rc2; 1994 + } 1995 + 1996 + if( p->rc==SQLITE_OK ){ 1997 + p->eStage = OTA_STAGE_CKPT; 1998 + p->nStep = (pState ? pState->nRow : 0); 1999 + p->aBuf = otaMalloc(p, p->pgsz); 2000 + p->iWalCksum = otaShmChecksum(p); 2001 + } 2002 + 2003 + if( p->rc==SQLITE_OK && pState && pState->iWalCksum!=p->iWalCksum ){ 2004 + p->rc = SQLITE_DONE; 2005 + p->eStage = OTA_STAGE_DONE; 2006 + } 2007 +} 2008 + 2009 +/* 2010 +** Called when iAmt bytes are read from offset iOff of the wal file while 2011 +** the ota object is in capture mode. Record the frame number of the frame 2012 +** being read in the aFrame[] array. 2013 +*/ 2014 +static int otaCaptureWalRead(sqlite3ota *pOta, i64 iOff, int iAmt){ 2015 + const u32 mReq = (1<<WAL_LOCK_WRITE)|(1<<WAL_LOCK_CKPT)|(1<<WAL_LOCK_READ0); 2016 + u32 iFrame; 2017 + 2018 + if( pOta->mLock!=mReq ){ 2019 + pOta->rc = SQLITE_BUSY; 2020 + return SQLITE_INTERNAL; 2021 + } 2022 + 2023 + pOta->pgsz = iAmt; 2024 + if( pOta->nFrame==pOta->nFrameAlloc ){ 2025 + int nNew = (pOta->nFrameAlloc ? pOta->nFrameAlloc : 64) * 2; 2026 + OtaFrame *aNew; 2027 + aNew = (OtaFrame*)sqlite3_realloc(pOta->aFrame, nNew * sizeof(OtaFrame)); 2028 + if( aNew==0 ) return SQLITE_NOMEM; 2029 + pOta->aFrame = aNew; 2030 + pOta->nFrameAlloc = nNew; 2031 + } 2032 + 2033 + iFrame = (u32)((iOff-32) / (i64)(iAmt+24)) + 1; 2034 + if( pOta->iMaxFrame<iFrame ) pOta->iMaxFrame = iFrame; 2035 + pOta->aFrame[pOta->nFrame].iWalFrame = iFrame; 2036 + pOta->aFrame[pOta->nFrame].iDbPage = 0; 2037 + pOta->nFrame++; 2038 + return SQLITE_OK; 2039 +} 2040 + 2041 +/* 2042 +** Called when a page of data is written to offset iOff of the database 2043 +** file while the ota handle is in capture mode. Record the page number 2044 +** of the page being written in the aFrame[] array. 2045 +*/ 2046 +static int otaCaptureDbWrite(sqlite3ota *pOta, i64 iOff){ 2047 + pOta->aFrame[pOta->nFrame-1].iDbPage = (u32)(iOff / pOta->pgsz) + 1; 2048 + return SQLITE_OK; 2049 +} 2050 + 2051 +/* 2052 +** This is called as part of an incremental checkpoint operation. Copy 2053 +** a single frame of data from the wal file into the database file, as 2054 +** indicated by the OtaFrame object. 2055 +*/ 2056 +static void otaCheckpointFrame(sqlite3ota *p, OtaFrame *pFrame){ 2057 + sqlite3_file *pWal = p->pTargetFd->pWalFd->pReal; 2058 + sqlite3_file *pDb = p->pTargetFd->pReal; 2059 + i64 iOff; 2060 + 2061 + assert( p->rc==SQLITE_OK ); 2062 + iOff = (i64)(pFrame->iWalFrame-1) * (p->pgsz + 24) + 32 + 24; 2063 + p->rc = pWal->pMethods->xRead(pWal, p->aBuf, p->pgsz, iOff); 2064 + if( p->rc ) return; 2065 + 2066 + iOff = (i64)(pFrame->iDbPage-1) * p->pgsz; 2067 + p->rc = pDb->pMethods->xWrite(pDb, p->aBuf, p->pgsz, iOff); 2068 +} 2069 + 2070 + 2071 +/* 2072 +** Take an EXCLUSIVE lock on the database file. 2073 +*/ 2074 +static void otaLockDatabase(sqlite3ota *p){ 2075 + sqlite3_file *pReal = p->pTargetFd->pReal; 2076 + assert( p->rc==SQLITE_OK ); 2077 + p->rc = pReal->pMethods->xLock(pReal, SQLITE_LOCK_SHARED); 2078 + if( p->rc==SQLITE_OK ){ 2079 + p->rc = pReal->pMethods->xLock(pReal, SQLITE_LOCK_EXCLUSIVE); 2080 + } 2081 +} 2082 + 2083 +/* 2084 +** The OTA handle is currently in OTA_STAGE_OAL state, with a SHARED lock 2085 +** on the database file. This proc moves the *-oal file to the *-wal path, 2086 +** then reopens the database file (this time in vanilla, non-oal, WAL mode). 2087 +** If an error occurs, leave an error code and error message in the ota 2088 +** handle. 2089 +*/ 2090 +static void otaMoveOalFile(sqlite3ota *p){ 2091 + const char *zBase = sqlite3_db_filename(p->dbMain, "main"); 2092 + 2093 + char *zWal = sqlite3_mprintf("%s-wal", zBase); 2094 + char *zOal = sqlite3_mprintf("%s-oal", zBase); 2095 + 2096 + assert( p->eStage==OTA_STAGE_MOVE ); 2097 + assert( p->rc==SQLITE_OK && p->zErrmsg==0 ); 2098 + if( zWal==0 || zOal==0 ){ 2099 + p->rc = SQLITE_NOMEM; 2100 + }else{ 2101 + /* Move the *-oal file to *-wal. At this point connection p->db is 2102 + ** holding a SHARED lock on the target database file (because it is 2103 + ** in WAL mode). So no other connection may be writing the db. 2104 + ** 2105 + ** In order to ensure that there are no database readers, an EXCLUSIVE 2106 + ** lock is obtained here before the *-oal is moved to *-wal. 2107 + */ 2108 + otaLockDatabase(p); 2109 + if( p->rc==SQLITE_OK ){ 2110 + otaFileSuffix3(zBase, zWal); 2111 + otaFileSuffix3(zBase, zOal); 2112 + 2113 + /* Re-open the databases. */ 2114 + otaObjIterFinalize(&p->objiter); 2115 + sqlite3_close(p->dbMain); 2116 + sqlite3_close(p->dbOta); 2117 + p->rc = rename(zOal, zWal) ? SQLITE_IOERR : SQLITE_OK; 2118 + if( p->rc==SQLITE_OK ){ 2119 + p->dbMain = 0; 2120 + p->dbOta = 0; 2121 + otaOpenDatabase(p); 2122 + otaSetupCheckpoint(p, 0); 2123 + } 2124 + } 2125 + } 2126 + 2127 + sqlite3_free(zWal); 2128 + sqlite3_free(zOal); 2129 +} 2130 + 2131 +/* 2132 +** The SELECT statement iterating through the keys for the current object 2133 +** (p->objiter.pSelect) currently points to a valid row. This function 2134 +** determines the type of operation requested by this row and returns 2135 +** one of the following values to indicate the result: 2136 +** 2137 +** * OTA_INSERT 2138 +** * OTA_DELETE 2139 +** * OTA_IDX_DELETE 2140 +** * OTA_UPDATE 2141 +** 2142 +** If OTA_UPDATE is returned, then output variable *pzMask is set to 2143 +** point to the text value indicating the columns to update. 2144 +** 2145 +** If the ota_control field contains an invalid value, an error code and 2146 +** message are left in the OTA handle and zero returned. 2147 +*/ 2148 +static int otaStepType(sqlite3ota *p, const char **pzMask){ 2149 + int iCol = p->objiter.nCol; /* Index of ota_control column */ 2150 + int res = 0; /* Return value */ 2151 + 2152 + switch( sqlite3_column_type(p->objiter.pSelect, iCol) ){ 2153 + case SQLITE_INTEGER: { 2154 + int iVal = sqlite3_column_int(p->objiter.pSelect, iCol); 2155 + if( iVal==0 ){ 2156 + res = OTA_INSERT; 2157 + }else if( iVal==1 ){ 2158 + res = OTA_DELETE; 2159 + }else if( iVal==2 ){ 2160 + res = OTA_IDX_DELETE; 2161 + }else if( iVal==3 ){ 2162 + res = OTA_IDX_INSERT; 2163 + } 2164 + break; 2165 + } 2166 + 2167 + case SQLITE_TEXT: { 2168 + const unsigned char *z = sqlite3_column_text(p->objiter.pSelect, iCol); 2169 + if( z==0 ){ 2170 + p->rc = SQLITE_NOMEM; 2171 + }else{ 2172 + *pzMask = (const char*)z; 2173 + } 2174 + res = OTA_UPDATE; 2175 + 2176 + break; 2177 + } 2178 + 2179 + default: 2180 + break; 2181 + } 2182 + 2183 + if( res==0 ){ 2184 + otaBadControlError(p); 2185 + } 2186 + return res; 2187 +} 2188 + 2189 +#ifdef SQLITE_DEBUG 2190 +/* 2191 +** Assert that column iCol of statement pStmt is named zName. 2192 +*/ 2193 +static void assertColumnName(sqlite3_stmt *pStmt, int iCol, const char *zName){ 2194 + const char *zCol = sqlite3_column_name(pStmt, iCol); 2195 + assert( 0==sqlite3_stricmp(zName, zCol) ); 2196 +} 2197 +#else 2198 +# define assertColumnName(x,y,z) 2199 +#endif 2200 + 2201 +/* 2202 +** This function does the work for an sqlite3ota_step() call. 2203 +** 2204 +** The object-iterator (p->objiter) currently points to a valid object, 2205 +** and the input cursor (p->objiter.pSelect) currently points to a valid 2206 +** input row. Perform whatever processing is required and return. 2207 +** 2208 +** If no error occurs, SQLITE_OK is returned. Otherwise, an error code 2209 +** and message is left in the OTA handle and a copy of the error code 2210 +** returned. 2211 +*/ 2212 +static int otaStep(sqlite3ota *p){ 2213 + OtaObjIter *pIter = &p->objiter; 2214 + const char *zMask = 0; 2215 + int i; 2216 + int eType = otaStepType(p, &zMask); 2217 + 2218 + if( eType ){ 2219 + assert( eType!=OTA_UPDATE || pIter->zIdx==0 ); 2220 + 2221 + if( pIter->zIdx==0 && eType==OTA_IDX_DELETE ){ 2222 + otaBadControlError(p); 2223 + } 2224 + else if( 2225 + eType==OTA_INSERT 2226 + || eType==OTA_DELETE 2227 + || eType==OTA_IDX_DELETE 2228 + || eType==OTA_IDX_INSERT 2229 + ){ 2230 + sqlite3_value *pVal; 2231 + sqlite3_stmt *pWriter; 2232 + 2233 + assert( eType!=OTA_UPDATE ); 2234 + assert( eType!=OTA_DELETE || pIter->zIdx==0 ); 2235 + 2236 + if( eType==OTA_IDX_DELETE || eType==OTA_DELETE ){ 2237 + pWriter = pIter->pDelete; 2238 + }else{ 2239 + pWriter = pIter->pInsert; 2240 + } 2241 + 2242 + for(i=0; i<pIter->nCol; i++){ 2243 + /* If this is an INSERT into a table b-tree and the table has an 2244 + ** explicit INTEGER PRIMARY KEY, check that this is not an attempt 2245 + ** to write a NULL into the IPK column. That is not permitted. */ 2246 + if( eType==OTA_INSERT 2247 + && pIter->zIdx==0 && pIter->eType==OTA_PK_IPK && pIter->abTblPk[i] 2248 + && sqlite3_column_type(pIter->pSelect, i)==SQLITE_NULL 2249 + ){ 2250 + p->rc = SQLITE_MISMATCH; 2251 + p->zErrmsg = sqlite3_mprintf("datatype mismatch"); 2252 + goto step_out; 2253 + } 2254 + 2255 + if( eType==OTA_DELETE && pIter->abTblPk[i]==0 ){ 2256 + continue; 2257 + } 2258 + 2259 + pVal = sqlite3_column_value(pIter->pSelect, i); 2260 + p->rc = sqlite3_bind_value(pWriter, i+1, pVal); 2261 + if( p->rc ) goto step_out; 2262 + } 2263 + if( pIter->zIdx==0 2264 + && (pIter->eType==OTA_PK_VTAB || pIter->eType==OTA_PK_NONE) 2265 + ){ 2266 + /* For a virtual table, or a table with no primary key, the 2267 + ** SELECT statement is: 2268 + ** 2269 + ** SELECT <cols>, ota_control, ota_rowid FROM .... 2270 + ** 2271 + ** Hence column_value(pIter->nCol+1). 2272 + */ 2273 + assertColumnName(pIter->pSelect, pIter->nCol+1, "ota_rowid"); 2274 + pVal = sqlite3_column_value(pIter->pSelect, pIter->nCol+1); 2275 + p->rc = sqlite3_bind_value(pWriter, pIter->nCol+1, pVal); 2276 + } 2277 + if( p->rc==SQLITE_OK ){ 2278 + sqlite3_step(pWriter); 2279 + p->rc = resetAndCollectError(pWriter, &p->zErrmsg); 2280 + } 2281 + }else{ 2282 + sqlite3_value *pVal; 2283 + sqlite3_stmt *pUpdate = 0; 2284 + assert( eType==OTA_UPDATE ); 2285 + otaGetUpdateStmt(p, pIter, zMask, &pUpdate); 2286 + if( pUpdate ){ 2287 + for(i=0; p->rc==SQLITE_OK && i<pIter->nCol; i++){ 2288 + char c = zMask[pIter->aiSrcOrder[i]]; 2289 + pVal = sqlite3_column_value(pIter->pSelect, i); 2290 + if( pIter->abTblPk[i] || c=='x' || c=='d' ){ 2291 + p->rc = sqlite3_bind_value(pUpdate, i+1, pVal); 2292 + } 2293 + } 2294 + if( p->rc==SQLITE_OK 2295 + && (pIter->eType==OTA_PK_VTAB || pIter->eType==OTA_PK_NONE) 2296 + ){ 2297 + /* Bind the ota_rowid value to column _rowid_ */ 2298 + assertColumnName(pIter->pSelect, pIter->nCol+1, "ota_rowid"); 2299 + pVal = sqlite3_column_value(pIter->pSelect, pIter->nCol+1); 2300 + p->rc = sqlite3_bind_value(pUpdate, pIter->nCol+1, pVal); 2301 + } 2302 + if( p->rc==SQLITE_OK ){ 2303 + sqlite3_step(pUpdate); 2304 + p->rc = resetAndCollectError(pUpdate, &p->zErrmsg); 2305 + } 2306 + } 2307 + } 2308 + } 2309 + 2310 + step_out: 2311 + return p->rc; 2312 +} 2313 + 2314 +/* 2315 +** Increment the schema cookie of the main database opened by p->dbMain. 2316 +*/ 2317 +static void otaIncrSchemaCookie(sqlite3ota *p){ 2318 + if( p->rc==SQLITE_OK ){ 2319 + int iCookie = 1000000; 2320 + sqlite3_stmt *pStmt; 2321 + 2322 + p->rc = prepareAndCollectError(p->dbMain, &pStmt, &p->zErrmsg, 2323 + "PRAGMA schema_version" 2324 + ); 2325 + if( p->rc==SQLITE_OK ){ 2326 + /* Coverage: it may be that this sqlite3_step() cannot fail. There 2327 + ** is already a transaction open, so the prepared statement cannot 2328 + ** throw an SQLITE_SCHEMA exception. The only database page the 2329 + ** statement reads is page 1, which is guaranteed to be in the cache. 2330 + ** And no memory allocations are required. */ 2331 + if( SQLITE_ROW==sqlite3_step(pStmt) ){ 2332 + iCookie = sqlite3_column_int(pStmt, 0); 2333 + } 2334 + otaFinalize(p, pStmt); 2335 + } 2336 + if( p->rc==SQLITE_OK ){ 2337 + otaMPrintfExec(p, p->dbMain, "PRAGMA schema_version = %d", iCookie+1); 2338 + } 2339 + } 2340 +} 2341 + 2342 +/* 2343 +** Update the contents of the ota_state table within the ota database. The 2344 +** value stored in the OTA_STATE_STAGE column is eStage. All other values 2345 +** are determined by inspecting the ota handle passed as the first argument. 2346 +*/ 2347 +static void otaSaveState(sqlite3ota *p, int eStage){ 2348 + if( p->rc==SQLITE_OK || p->rc==SQLITE_DONE ){ 2349 + sqlite3_stmt *pInsert = 0; 2350 + int rc; 2351 + 2352 + assert( p->zErrmsg==0 ); 2353 + rc = prepareFreeAndCollectError(p->dbOta, &pInsert, &p->zErrmsg, 2354 + sqlite3_mprintf( 2355 + "INSERT OR REPLACE INTO %s.ota_state(k, v) VALUES " 2356 + "(%d, %d), " 2357 + "(%d, %Q), " 2358 + "(%d, %Q), " 2359 + "(%d, %d), " 2360 + "(%d, %d), " 2361 + "(%d, %lld), " 2362 + "(%d, %lld), " 2363 + "(%d, %lld) ", 2364 + p->zStateDb, 2365 + OTA_STATE_STAGE, eStage, 2366 + OTA_STATE_TBL, p->objiter.zTbl, 2367 + OTA_STATE_IDX, p->objiter.zIdx, 2368 + OTA_STATE_ROW, p->nStep, 2369 + OTA_STATE_PROGRESS, p->nProgress, 2370 + OTA_STATE_CKPT, p->iWalCksum, 2371 + OTA_STATE_COOKIE, (i64)p->pTargetFd->iCookie, 2372 + OTA_STATE_OALSZ, p->iOalSz 2373 + ) 2374 + ); 2375 + assert( pInsert==0 || rc==SQLITE_OK ); 2376 + 2377 + if( rc==SQLITE_OK ){ 2378 + sqlite3_step(pInsert); 2379 + rc = sqlite3_finalize(pInsert); 2380 + } 2381 + if( rc!=SQLITE_OK ) p->rc = rc; 2382 + } 2383 +} 2384 + 2385 + 2386 +/* 2387 +** Step the OTA object. 2388 +*/ 2389 +int sqlite3ota_step(sqlite3ota *p){ 2390 + if( p ){ 2391 + switch( p->eStage ){ 2392 + case OTA_STAGE_OAL: { 2393 + OtaObjIter *pIter = &p->objiter; 2394 + while( p->rc==SQLITE_OK && pIter->zTbl ){ 2395 + 2396 + if( pIter->bCleanup ){ 2397 + /* Clean up the ota_tmp_xxx table for the previous table. It 2398 + ** cannot be dropped as there are currently active SQL statements. 2399 + ** But the contents can be deleted. */ 2400 + if( pIter->abIndexed ){ 2401 + otaMPrintfExec(p, p->dbOta, 2402 + "DELETE FROM %s.'ota_tmp_%q'", p->zStateDb, pIter->zTbl 2403 + ); 2404 + } 2405 + }else{ 2406 + otaObjIterPrepareAll(p, pIter, 0); 2407 + 2408 + /* Advance to the next row to process. */ 2409 + if( p->rc==SQLITE_OK ){ 2410 + int rc = sqlite3_step(pIter->pSelect); 2411 + if( rc==SQLITE_ROW ){ 2412 + p->nProgress++; 2413 + p->nStep++; 2414 + return otaStep(p); 2415 + } 2416 + p->rc = sqlite3_reset(pIter->pSelect); 2417 + p->nStep = 0; 2418 + } 2419 + } 2420 + 2421 + otaObjIterNext(p, pIter); 2422 + } 2423 + 2424 + if( p->rc==SQLITE_OK ){ 2425 + assert( pIter->zTbl==0 ); 2426 + otaSaveState(p, OTA_STAGE_MOVE); 2427 + otaIncrSchemaCookie(p); 2428 + if( p->rc==SQLITE_OK ){ 2429 + p->rc = sqlite3_exec(p->dbMain, "COMMIT", 0, 0, &p->zErrmsg); 2430 + } 2431 + if( p->rc==SQLITE_OK ){ 2432 + p->rc = sqlite3_exec(p->dbOta, "COMMIT", 0, 0, &p->zErrmsg); 2433 + } 2434 + p->eStage = OTA_STAGE_MOVE; 2435 + } 2436 + break; 2437 + } 2438 + 2439 + case OTA_STAGE_MOVE: { 2440 + if( p->rc==SQLITE_OK ){ 2441 + otaMoveOalFile(p); 2442 + p->nProgress++; 2443 + } 2444 + break; 2445 + } 2446 + 2447 + case OTA_STAGE_CKPT: { 2448 + if( p->rc==SQLITE_OK ){ 2449 + if( p->nStep>=p->nFrame ){ 2450 + sqlite3_file *pDb = p->pTargetFd->pReal; 2451 + 2452 + /* Sync the db file */ 2453 + p->rc = pDb->pMethods->xSync(pDb, SQLITE_SYNC_NORMAL); 2454 + 2455 + /* Update nBackfill */ 2456 + if( p->rc==SQLITE_OK ){ 2457 + void volatile *ptr; 2458 + p->rc = pDb->pMethods->xShmMap(pDb, 0, 32*1024, 0, &ptr); 2459 + if( p->rc==SQLITE_OK ){ 2460 + ((u32 volatile*)ptr)[24] = p->iMaxFrame; 2461 + } 2462 + } 2463 + 2464 + if( p->rc==SQLITE_OK ){ 2465 + p->eStage = OTA_STAGE_DONE; 2466 + p->rc = SQLITE_DONE; 2467 + } 2468 + }else{ 2469 + OtaFrame *pFrame = &p->aFrame[p->nStep]; 2470 + otaCheckpointFrame(p, pFrame); 2471 + p->nStep++; 2472 + } 2473 + p->nProgress++; 2474 + } 2475 + break; 2476 + } 2477 + 2478 + default: 2479 + break; 2480 + } 2481 + return p->rc; 2482 + }else{ 2483 + return SQLITE_NOMEM; 2484 + } 2485 +} 2486 + 2487 +/* 2488 +** Free an OtaState object allocated by otaLoadState(). 2489 +*/ 2490 +static void otaFreeState(OtaState *p){ 2491 + if( p ){ 2492 + sqlite3_free(p->zTbl); 2493 + sqlite3_free(p->zIdx); 2494 + sqlite3_free(p); 2495 + } 2496 +} 2497 + 2498 +/* 2499 +** Allocate an OtaState object and load the contents of the ota_state 2500 +** table into it. Return a pointer to the new object. It is the 2501 +** responsibility of the caller to eventually free the object using 2502 +** sqlite3_free(). 2503 +** 2504 +** If an error occurs, leave an error code and message in the ota handle 2505 +** and return NULL. 2506 +*/ 2507 +static OtaState *otaLoadState(sqlite3ota *p){ 2508 + OtaState *pRet = 0; 2509 + sqlite3_stmt *pStmt = 0; 2510 + int rc; 2511 + int rc2; 2512 + 2513 + pRet = (OtaState*)otaMalloc(p, sizeof(OtaState)); 2514 + if( pRet==0 ) return 0; 2515 + 2516 + rc = prepareFreeAndCollectError(p->dbOta, &pStmt, &p->zErrmsg, 2517 + sqlite3_mprintf("SELECT k, v FROM %s.ota_state", p->zStateDb) 2518 + ); 2519 + while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ 2520 + switch( sqlite3_column_int(pStmt, 0) ){ 2521 + case OTA_STATE_STAGE: 2522 + pRet->eStage = sqlite3_column_int(pStmt, 1); 2523 + if( pRet->eStage!=OTA_STAGE_OAL 2524 + && pRet->eStage!=OTA_STAGE_MOVE 2525 + && pRet->eStage!=OTA_STAGE_CKPT 2526 + ){ 2527 + p->rc = SQLITE_CORRUPT; 2528 + } 2529 + break; 2530 + 2531 + case OTA_STATE_TBL: 2532 + pRet->zTbl = otaStrndup((char*)sqlite3_column_text(pStmt, 1), &rc); 2533 + break; 2534 + 2535 + case OTA_STATE_IDX: 2536 + pRet->zIdx = otaStrndup((char*)sqlite3_column_text(pStmt, 1), &rc); 2537 + break; 2538 + 2539 + case OTA_STATE_ROW: 2540 + pRet->nRow = sqlite3_column_int(pStmt, 1); 2541 + break; 2542 + 2543 + case OTA_STATE_PROGRESS: 2544 + pRet->nProgress = sqlite3_column_int64(pStmt, 1); 2545 + break; 2546 + 2547 + case OTA_STATE_CKPT: 2548 + pRet->iWalCksum = sqlite3_column_int64(pStmt, 1); 2549 + break; 2550 + 2551 + case OTA_STATE_COOKIE: 2552 + pRet->iCookie = (u32)sqlite3_column_int64(pStmt, 1); 2553 + break; 2554 + 2555 + case OTA_STATE_OALSZ: 2556 + pRet->iOalSz = (u32)sqlite3_column_int64(pStmt, 1); 2557 + break; 2558 + 2559 + default: 2560 + rc = SQLITE_CORRUPT; 2561 + break; 2562 + } 2563 + } 2564 + rc2 = sqlite3_finalize(pStmt); 2565 + if( rc==SQLITE_OK ) rc = rc2; 2566 + 2567 + p->rc = rc; 2568 + return pRet; 2569 +} 2570 + 2571 +/* 2572 +** Compare strings z1 and z2, returning 0 if they are identical, or non-zero 2573 +** otherwise. Either or both argument may be NULL. Two NULL values are 2574 +** considered equal, and NULL is considered distinct from all other values. 2575 +*/ 2576 +static int otaStrCompare(const char *z1, const char *z2){ 2577 + if( z1==0 && z2==0 ) return 0; 2578 + if( z1==0 || z2==0 ) return 1; 2579 + return (sqlite3_stricmp(z1, z2)!=0); 2580 +} 2581 + 2582 +/* 2583 +** This function is called as part of sqlite3ota_open() when initializing 2584 +** an ota handle in OAL stage. If the ota update has not started (i.e. 2585 +** the ota_state table was empty) it is a no-op. Otherwise, it arranges 2586 +** things so that the next call to sqlite3ota_step() continues on from 2587 +** where the previous ota handle left off. 2588 +** 2589 +** If an error occurs, an error code and error message are left in the 2590 +** ota handle passed as the first argument. 2591 +*/ 2592 +static void otaSetupOal(sqlite3ota *p, OtaState *pState){ 2593 + assert( p->rc==SQLITE_OK ); 2594 + if( pState->zTbl ){ 2595 + OtaObjIter *pIter = &p->objiter; 2596 + int rc = SQLITE_OK; 2597 + 2598 + while( rc==SQLITE_OK && pIter->zTbl && (pIter->bCleanup 2599 + || otaStrCompare(pIter->zIdx, pState->zIdx) 2600 + || otaStrCompare(pIter->zTbl, pState->zTbl) 2601 + )){ 2602 + rc = otaObjIterNext(p, pIter); 2603 + } 2604 + 2605 + if( rc==SQLITE_OK && !pIter->zTbl ){ 2606 + rc = SQLITE_ERROR; 2607 + p->zErrmsg = sqlite3_mprintf("ota_state mismatch error"); 2608 + } 2609 + 2610 + if( rc==SQLITE_OK ){ 2611 + p->nStep = pState->nRow; 2612 + rc = otaObjIterPrepareAll(p, &p->objiter, p->nStep); 2613 + } 2614 + 2615 + p->rc = rc; 2616 + } 2617 +} 2618 + 2619 +/* 2620 +** If there is a "*-oal" file in the file-system corresponding to the 2621 +** target database in the file-system, delete it. If an error occurs, 2622 +** leave an error code and error message in the ota handle. 2623 +*/ 2624 +static void otaDeleteOalFile(sqlite3ota *p){ 2625 + char *zOal = sqlite3_mprintf("%s-oal", p->zTarget); 2626 + assert( p->rc==SQLITE_OK && p->zErrmsg==0 ); 2627 + unlink(zOal); 2628 + sqlite3_free(zOal); 2629 +} 2630 + 2631 +/* 2632 +** Allocate a private ota VFS for the ota handle passed as the only 2633 +** argument. This VFS will be used unless the call to sqlite3ota_open() 2634 +** specified a URI with a vfs=? option in place of a target database 2635 +** file name. 2636 +*/ 2637 +static void otaCreateVfs(sqlite3ota *p){ 2638 + int rnd; 2639 + char zRnd[64]; 2640 + 2641 + assert( p->rc==SQLITE_OK ); 2642 + sqlite3_randomness(sizeof(int), (void*)&rnd); 2643 + sprintf(zRnd, "ota_vfs_%d", rnd); 2644 + p->rc = sqlite3ota_create_vfs(zRnd, 0); 2645 + if( p->rc==SQLITE_OK ){ 2646 + sqlite3_vfs *pVfs = sqlite3_vfs_find(zRnd); 2647 + assert( pVfs ); 2648 + p->zVfsName = pVfs->zName; 2649 + } 2650 +} 2651 + 2652 +/* 2653 +** Destroy the private VFS created for the ota handle passed as the only 2654 +** argument by an earlier call to otaCreateVfs(). 2655 +*/ 2656 +static void otaDeleteVfs(sqlite3ota *p){ 2657 + if( p->zVfsName ){ 2658 + sqlite3ota_destroy_vfs(p->zVfsName); 2659 + p->zVfsName = 0; 2660 + } 2661 +} 2662 + 2663 +static sqlite3ota *otaOpen( 2664 + const char *zTarget, 2665 + const char *zOta, 2666 + const char *zState 2667 +){ 2668 + sqlite3ota *p; 2669 + int nTarget = strlen(zTarget); 2670 + int nOta = strlen(zOta); 2671 + int nState = zState ? strlen(zState) : 0; 2672 + 2673 + p = (sqlite3ota*)sqlite3_malloc(sizeof(sqlite3ota)+nTarget+1+nOta+1+nState+1); 2674 + if( p ){ 2675 + OtaState *pState = 0; 2676 + 2677 + /* Create the custom VFS. */ 2678 + memset(p, 0, sizeof(sqlite3ota)); 2679 + otaCreateVfs(p); 2680 + 2681 + /* Open the target database */ 2682 + if( p->rc==SQLITE_OK ){ 2683 + p->zTarget = (char*)&p[1]; 2684 + memcpy(p->zTarget, zTarget, nTarget+1); 2685 + p->zOta = &p->zTarget[nTarget+1]; 2686 + memcpy(p->zOta, zOta, nOta+1); 2687 + if( zState ){ 2688 + p->zState = &p->zOta[nOta+1]; 2689 + memcpy(p->zState, zState, nState+1); 2690 + } 2691 + otaOpenDatabase(p); 2692 + } 2693 + 2694 + /* If it has not already been created, create the ota_state table */ 2695 + otaMPrintfExec(p, p->dbOta, OTA_CREATE_STATE, p->zStateDb); 2696 + 2697 + if( p->rc==SQLITE_OK ){ 2698 + pState = otaLoadState(p); 2699 + assert( pState || p->rc!=SQLITE_OK ); 2700 + if( p->rc==SQLITE_OK ){ 2701 + 2702 + if( pState->eStage==0 ){ 2703 + otaDeleteOalFile(p); 2704 + p->eStage = OTA_STAGE_OAL; 2705 + }else{ 2706 + p->eStage = pState->eStage; 2707 + } 2708 + p->nProgress = pState->nProgress; 2709 + p->iOalSz = pState->iOalSz; 2710 + } 2711 + } 2712 + assert( p->rc!=SQLITE_OK || p->eStage!=0 ); 2713 + 2714 + if( p->rc==SQLITE_OK && p->pTargetFd->pWalFd ){ 2715 + if( p->eStage==OTA_STAGE_OAL ){ 2716 + p->rc = SQLITE_ERROR; 2717 + p->zErrmsg = sqlite3_mprintf("cannot update wal mode database"); 2718 + }else if( p->eStage==OTA_STAGE_MOVE ){ 2719 + p->eStage = OTA_STAGE_CKPT; 2720 + p->nStep = 0; 2721 + } 2722 + } 2723 + 2724 + if( p->rc==SQLITE_OK 2725 + && (p->eStage==OTA_STAGE_OAL || p->eStage==OTA_STAGE_MOVE) 2726 + && pState->eStage!=0 && p->pTargetFd->iCookie!=pState->iCookie 2727 + ){ 2728 + /* At this point (pTargetFd->iCookie) contains the value of the 2729 + ** change-counter cookie (the thing that gets incremented when a 2730 + ** transaction is committed in rollback mode) currently stored on 2731 + ** page 1 of the database file. */ 2732 + p->rc = SQLITE_BUSY; 2733 + p->zErrmsg = sqlite3_mprintf("database modified during ota update"); 2734 + } 2735 + 2736 + if( p->rc==SQLITE_OK ){ 2737 + if( p->eStage==OTA_STAGE_OAL ){ 2738 + 2739 + /* Open transactions both databases. The *-oal file is opened or 2740 + ** created at this point. */ 2741 + p->rc = sqlite3_exec(p->dbMain, "BEGIN IMMEDIATE", 0, 0, &p->zErrmsg); 2742 + if( p->rc==SQLITE_OK ){ 2743 + p->rc = sqlite3_exec(p->dbOta, "BEGIN IMMEDIATE", 0, 0, &p->zErrmsg); 2744 + } 2745 + 2746 + /* Point the object iterator at the first object */ 2747 + if( p->rc==SQLITE_OK ){ 2748 + p->rc = otaObjIterFirst(p, &p->objiter); 2749 + } 2750 + 2751 + /* If the OTA database contains no data_xxx tables, declare the OTA 2752 + ** update finished. */ 2753 + if( p->rc==SQLITE_OK && p->objiter.zTbl==0 ){ 2754 + p->rc = SQLITE_DONE; 2755 + } 2756 + 2757 + if( p->rc==SQLITE_OK ){ 2758 + otaSetupOal(p, pState); 2759 + } 2760 + 2761 + }else if( p->eStage==OTA_STAGE_MOVE ){ 2762 + /* no-op */ 2763 + }else if( p->eStage==OTA_STAGE_CKPT ){ 2764 + otaSetupCheckpoint(p, pState); 2765 + }else if( p->eStage==OTA_STAGE_DONE ){ 2766 + p->rc = SQLITE_DONE; 2767 + }else{ 2768 + p->rc = SQLITE_CORRUPT; 2769 + } 2770 + } 2771 + 2772 + otaFreeState(pState); 2773 + } 2774 + 2775 + return p; 2776 +} 2777 + 2778 + 2779 +/* 2780 +** Open and return a new OTA handle. 2781 +*/ 2782 +sqlite3ota *sqlite3ota_open_v2( 2783 + const char *zDb, 2784 + const char *zOta, 2785 + const char *zState 2786 +){ 2787 + return otaOpen(zDb, zOta, zState); 2788 +} 2789 + 2790 +/* 2791 +** Open and return a new OTA handle. 2792 +*/ 2793 +sqlite3ota *sqlite3ota_open( 2794 + const char *zDb, 2795 + const char *zOta 2796 +){ 2797 + return otaOpen(zDb, zOta, 0); 2798 +} 2799 + 2800 +/* 2801 +** Return the database handle used by pOta. 2802 +*/ 2803 +sqlite3 *sqlite3ota_db(sqlite3ota *pOta, int bOta){ 2804 + sqlite3 *db = 0; 2805 + if( pOta ){ 2806 + db = (bOta ? pOta->dbOta : pOta->dbMain); 2807 + } 2808 + return db; 2809 +} 2810 + 2811 + 2812 +/* 2813 +** If the error code currently stored in the OTA handle is SQLITE_CONSTRAINT, 2814 +** then edit any error message string so as to remove all occurrences of 2815 +** the pattern "ota_imp_[0-9]*". 2816 +*/ 2817 +static void otaEditErrmsg(sqlite3ota *p){ 2818 + if( p->rc==SQLITE_CONSTRAINT && p->zErrmsg ){ 2819 + int i; 2820 + int nErrmsg = strlen(p->zErrmsg); 2821 + for(i=0; i<(nErrmsg-8); i++){ 2822 + if( memcmp(&p->zErrmsg[i], "ota_imp_", 8)==0 ){ 2823 + int nDel = 8; 2824 + while( p->zErrmsg[i+nDel]>='0' && p->zErrmsg[i+nDel]<='9' ) nDel++; 2825 + memmove(&p->zErrmsg[i], &p->zErrmsg[i+nDel], nErrmsg + 1 - i - nDel); 2826 + nErrmsg -= nDel; 2827 + } 2828 + } 2829 + } 2830 +} 2831 + 2832 +/* 2833 +** Close the OTA handle. 2834 +*/ 2835 +int sqlite3ota_close(sqlite3ota *p, char **pzErrmsg){ 2836 + int rc; 2837 + if( p ){ 2838 + 2839 + /* Commit the transaction to the *-oal file. */ 2840 + if( p->rc==SQLITE_OK && p->eStage==OTA_STAGE_OAL ){ 2841 + p->rc = sqlite3_exec(p->dbMain, "COMMIT", 0, 0, &p->zErrmsg); 2842 + } 2843 + 2844 + otaSaveState(p, p->eStage); 2845 + 2846 + if( p->rc==SQLITE_OK && p->eStage==OTA_STAGE_OAL ){ 2847 + p->rc = sqlite3_exec(p->dbOta, "COMMIT", 0, 0, &p->zErrmsg); 2848 + } 2849 + 2850 + /* Close any open statement handles. */ 2851 + otaObjIterFinalize(&p->objiter); 2852 + 2853 + /* Close the open database handle and VFS object. */ 2854 + sqlite3_close(p->dbMain); 2855 + sqlite3_close(p->dbOta); 2856 + otaDeleteVfs(p); 2857 + sqlite3_free(p->aBuf); 2858 + sqlite3_free(p->aFrame); 2859 + 2860 + otaEditErrmsg(p); 2861 + rc = p->rc; 2862 + *pzErrmsg = p->zErrmsg; 2863 + sqlite3_free(p); 2864 + }else{ 2865 + rc = SQLITE_NOMEM; 2866 + *pzErrmsg = 0; 2867 + } 2868 + return rc; 2869 +} 2870 + 2871 +/* 2872 +** Return the total number of key-value operations (inserts, deletes or 2873 +** updates) that have been performed on the target database since the 2874 +** current OTA update was started. 2875 +*/ 2876 +sqlite3_int64 sqlite3ota_progress(sqlite3ota *pOta){ 2877 + return pOta->nProgress; 2878 +} 2879 + 2880 +/************************************************************************** 2881 +** Beginning of OTA VFS shim methods. The VFS shim modifies the behaviour 2882 +** of a standard VFS in the following ways: 2883 +** 2884 +** 1. Whenever the first page of a main database file is read or 2885 +** written, the value of the change-counter cookie is stored in 2886 +** ota_file.iCookie. Similarly, the value of the "write-version" 2887 +** database header field is stored in ota_file.iWriteVer. This ensures 2888 +** that the values are always trustworthy within an open transaction. 2889 +** 2890 +** 2. Whenever an SQLITE_OPEN_WAL file is opened, the (ota_file.pWalFd) 2891 +** member variable of the associated database file descriptor is set 2892 +** to point to the new file. A mutex protected linked list of all main 2893 +** db fds opened using a particular OTA VFS is maintained at 2894 +** ota_vfs.pMain to facilitate this. 2895 +** 2896 +** 3. Using a new file-control "SQLITE_FCNTL_OTA", a main db ota_file 2897 +** object can be marked as the target database of an OTA update. This 2898 +** turns on the following extra special behaviour: 2899 +** 2900 +** 3a. If xAccess() is called to check if there exists a *-wal file 2901 +** associated with an OTA target database currently in OTA_STAGE_OAL 2902 +** stage (preparing the *-oal file), the following special handling 2903 +** applies: 2904 +** 2905 +** * if the *-wal file does exist, return SQLITE_CANTOPEN. An OTA 2906 +** target database may not be in wal mode already. 2907 +** 2908 +** * if the *-wal file does not exist, set the output parameter to 2909 +** non-zero (to tell SQLite that it does exist) anyway. 2910 +** 2911 +** Then, when xOpen() is called to open the *-wal file associated with 2912 +** the OTA target in OTA_STAGE_OAL stage, instead of opening the *-wal 2913 +** file, the ota vfs opens the corresponding *-oal file instead. 2914 +** 2915 +** 3b. The *-shm pages returned by xShmMap() for a target db file in 2916 +** OTA_STAGE_OAL mode are actually stored in heap memory. This is to 2917 +** avoid creating a *-shm file on disk. Additionally, xShmLock() calls 2918 +** are no-ops on target database files in OTA_STAGE_OAL mode. This is 2919 +** because assert() statements in some VFS implementations fail if 2920 +** xShmLock() is called before xShmMap(). 2921 +** 2922 +** 3c. If an EXCLUSIVE lock is attempted on a target database file in any 2923 +** mode except OTA_STAGE_DONE (all work completed and checkpointed), it 2924 +** fails with an SQLITE_BUSY error. This is to stop OTA connections 2925 +** from automatically checkpointing a *-wal (or *-oal) file from within 2926 +** sqlite3_close(). 2927 +** 2928 +** 3d. In OTA_STAGE_CAPTURE mode, all xRead() calls on the wal file, and 2929 +** all xWrite() calls on the target database file perform no IO. 2930 +** Instead the frame and page numbers that would be read and written 2931 +** are recorded. Additionally, successful attempts to obtain exclusive 2932 +** xShmLock() WRITER, CHECKPOINTER and READ0 locks on the target 2933 +** database file are recorded. xShmLock() calls to unlock the same 2934 +** locks are no-ops (so that once obtained, these locks are never 2935 +** relinquished). Finally, calls to xSync() on the target database 2936 +** file fail with SQLITE_INTERNAL errors. 2937 +*/ 2938 + 2939 +static void otaUnlockShm(ota_file *p){ 2940 + if( p->pOta ){ 2941 + int (*xShmLock)(sqlite3_file*,int,int,int) = p->pReal->pMethods->xShmLock; 2942 + int i; 2943 + for(i=0; i<SQLITE_SHM_NLOCK;i++){ 2944 + if( (1<<i) & p->pOta->mLock ){ 2945 + xShmLock(p->pReal, i, 1, SQLITE_SHM_UNLOCK|SQLITE_SHM_EXCLUSIVE); 2946 + } 2947 + } 2948 + p->pOta->mLock = 0; 2949 + } 2950 +} 2951 + 2952 +/* 2953 +** Close an ota file. 2954 +*/ 2955 +static int otaVfsClose(sqlite3_file *pFile){ 2956 + ota_file *p = (ota_file*)pFile; 2957 + int rc; 2958 + int i; 2959 + 2960 + /* Free the contents of the apShm[] array. And the array itself. */ 2961 + for(i=0; i<p->nShm; i++){ 2962 + sqlite3_free(p->apShm[i]); 2963 + } 2964 + sqlite3_free(p->apShm); 2965 + p->apShm = 0; 2966 + sqlite3_free(p->zDel); 2967 + 2968 + if( p->openFlags & SQLITE_OPEN_MAIN_DB ){ 2969 + ota_file **pp; 2970 + sqlite3_mutex_enter(p->pOtaVfs->mutex); 2971 + for(pp=&p->pOtaVfs->pMain; *pp!=p; pp=&((*pp)->pMainNext)); 2972 + *pp = p->pMainNext; 2973 + sqlite3_mutex_leave(p->pOtaVfs->mutex); 2974 + otaUnlockShm(p); 2975 + p->pReal->pMethods->xShmUnmap(p->pReal, 0); 2976 + } 2977 + 2978 + /* Close the underlying file handle */ 2979 + rc = p->pReal->pMethods->xClose(p->pReal); 2980 + return rc; 2981 +} 2982 + 2983 + 2984 +/* 2985 +** Read and return an unsigned 32-bit big-endian integer from the buffer 2986 +** passed as the only argument. 2987 +*/ 2988 +static u32 otaGetU32(u8 *aBuf){ 2989 + return ((u32)aBuf[0] << 24) 2990 + + ((u32)aBuf[1] << 16) 2991 + + ((u32)aBuf[2] << 8) 2992 + + ((u32)aBuf[3]); 2993 +} 2994 + 2995 +/* 2996 +** Read data from an otaVfs-file. 2997 +*/ 2998 +static int otaVfsRead( 2999 + sqlite3_file *pFile, 3000 + void *zBuf, 3001 + int iAmt, 3002 + sqlite_int64 iOfst 3003 +){ 3004 + ota_file *p = (ota_file*)pFile; 3005 + sqlite3ota *pOta = p->pOta; 3006 + int rc; 3007 + 3008 + if( pOta && pOta->eStage==OTA_STAGE_CAPTURE ){ 3009 + assert( p->openFlags & SQLITE_OPEN_WAL ); 3010 + rc = otaCaptureWalRead(p->pOta, iOfst, iAmt); 3011 + }else{ 3012 + if( pOta && pOta->eStage==OTA_STAGE_OAL 3013 + && (p->openFlags & SQLITE_OPEN_WAL) 3014 + && iOfst>=pOta->iOalSz 3015 + ){ 3016 + rc = SQLITE_OK; 3017 + memset(zBuf, 0, iAmt); 3018 + }else{ 3019 + rc = p->pReal->pMethods->xRead(p->pReal, zBuf, iAmt, iOfst); 3020 + } 3021 + if( rc==SQLITE_OK && iOfst==0 && (p->openFlags & SQLITE_OPEN_MAIN_DB) ){ 3022 + /* These look like magic numbers. But they are stable, as they are part 3023 + ** of the definition of the SQLite file format, which may not change. */ 3024 + u8 *pBuf = (u8*)zBuf; 3025 + p->iCookie = otaGetU32(&pBuf[24]); 3026 + p->iWriteVer = pBuf[19]; 3027 + } 3028 + } 3029 + return rc; 3030 +} 3031 + 3032 +/* 3033 +** Write data to an otaVfs-file. 3034 +*/ 3035 +static int otaVfsWrite( 3036 + sqlite3_file *pFile, 3037 + const void *zBuf, 3038 + int iAmt, 3039 + sqlite_int64 iOfst 3040 +){ 3041 + ota_file *p = (ota_file*)pFile; 3042 + sqlite3ota *pOta = p->pOta; 3043 + int rc; 3044 + 3045 + if( pOta && pOta->eStage==OTA_STAGE_CAPTURE ){ 3046 + assert( p->openFlags & SQLITE_OPEN_MAIN_DB ); 3047 + rc = otaCaptureDbWrite(p->pOta, iOfst); 3048 + }else{ 3049 + if( pOta && pOta->eStage==OTA_STAGE_OAL 3050 + && (p->openFlags & SQLITE_OPEN_WAL) 3051 + && iOfst>=pOta->iOalSz 3052 + ){ 3053 + pOta->iOalSz = iAmt + iOfst; 3054 + } 3055 + rc = p->pReal->pMethods->xWrite(p->pReal, zBuf, iAmt, iOfst); 3056 + if( rc==SQLITE_OK && iOfst==0 && (p->openFlags & SQLITE_OPEN_MAIN_DB) ){ 3057 + /* These look like magic numbers. But they are stable, as they are part 3058 + ** of the definition of the SQLite file format, which may not change. */ 3059 + u8 *pBuf = (u8*)zBuf; 3060 + p->iCookie = otaGetU32(&pBuf[24]); 3061 + p->iWriteVer = pBuf[19]; 3062 + } 3063 + } 3064 + return rc; 3065 +} 3066 + 3067 +/* 3068 +** Truncate an otaVfs-file. 3069 +*/ 3070 +static int otaVfsTruncate(sqlite3_file *pFile, sqlite_int64 size){ 3071 + ota_file *p = (ota_file*)pFile; 3072 + return p->pReal->pMethods->xTruncate(p->pReal, size); 3073 +} 3074 + 3075 +/* 3076 +** Sync an otaVfs-file. 3077 +*/ 3078 +static int otaVfsSync(sqlite3_file *pFile, int flags){ 3079 + ota_file *p = (ota_file *)pFile; 3080 + if( p->pOta && p->pOta->eStage==OTA_STAGE_CAPTURE ){ 3081 + if( p->openFlags & SQLITE_OPEN_MAIN_DB ){ 3082 + return SQLITE_INTERNAL; 3083 + } 3084 + return SQLITE_OK; 3085 + } 3086 + return p->pReal->pMethods->xSync(p->pReal, flags); 3087 +} 3088 + 3089 +/* 3090 +** Return the current file-size of an otaVfs-file. 3091 +*/ 3092 +static int otaVfsFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){ 3093 + ota_file *p = (ota_file *)pFile; 3094 + return p->pReal->pMethods->xFileSize(p->pReal, pSize); 3095 +} 3096 + 3097 +/* 3098 +** Lock an otaVfs-file. 3099 +*/ 3100 +static int otaVfsLock(sqlite3_file *pFile, int eLock){ 3101 + ota_file *p = (ota_file*)pFile; 3102 + sqlite3ota *pOta = p->pOta; 3103 + int rc = SQLITE_OK; 3104 + 3105 + assert( p->openFlags & (SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_TEMP_DB) ); 3106 + if( pOta && eLock==SQLITE_LOCK_EXCLUSIVE && pOta->eStage!=OTA_STAGE_DONE ){ 3107 + /* Do not allow EXCLUSIVE locks. Preventing SQLite from taking this 3108 + ** prevents it from checkpointing the database from sqlite3_close(). */ 3109 + rc = SQLITE_BUSY; 3110 + }else{ 3111 + rc = p->pReal->pMethods->xLock(p->pReal, eLock); 3112 + } 3113 + 3114 + return rc; 3115 +} 3116 + 3117 +/* 3118 +** Unlock an otaVfs-file. 3119 +*/ 3120 +static int otaVfsUnlock(sqlite3_file *pFile, int eLock){ 3121 + ota_file *p = (ota_file *)pFile; 3122 + return p->pReal->pMethods->xUnlock(p->pReal, eLock); 3123 +} 3124 + 3125 +/* 3126 +** Check if another file-handle holds a RESERVED lock on an otaVfs-file. 3127 +*/ 3128 +static int otaVfsCheckReservedLock(sqlite3_file *pFile, int *pResOut){ 3129 + ota_file *p = (ota_file *)pFile; 3130 + return p->pReal->pMethods->xCheckReservedLock(p->pReal, pResOut); 3131 +} 3132 + 3133 +/* 3134 +** File control method. For custom operations on an otaVfs-file. 3135 +*/ 3136 +static int otaVfsFileControl(sqlite3_file *pFile, int op, void *pArg){ 3137 + ota_file *p = (ota_file *)pFile; 3138 + int (*xControl)(sqlite3_file*,int,void*) = p->pReal->pMethods->xFileControl; 3139 + int rc; 3140 + 3141 + assert( p->openFlags & 3142 + (SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_TEMP_DB|SQLITE_OPEN_TRANSIENT_DB) 3143 + ); 3144 + if( op==SQLITE_FCNTL_OTA ){ 3145 + sqlite3ota *pOta = (sqlite3ota*)pArg; 3146 + 3147 + /* First try to find another OTA vfs lower down in the vfs stack. If 3148 + ** one is found, this vfs will operate in pass-through mode. The lower 3149 + ** level vfs will do the special OTA handling. */ 3150 + rc = xControl(p->pReal, op, pArg); 3151 + 3152 + if( rc==SQLITE_NOTFOUND ){ 3153 + /* Now search for a zipvfs instance lower down in the VFS stack. If 3154 + ** one is found, this is an error. */ 3155 + void *dummy = 0; 3156 + rc = xControl(p->pReal, SQLITE_FCNTL_ZIPVFS, &dummy); 3157 + if( rc==SQLITE_OK ){ 3158 + rc = SQLITE_ERROR; 3159 + pOta->zErrmsg = sqlite3_mprintf("ota/zipvfs setup error"); 3160 + }else if( rc==SQLITE_NOTFOUND ){ 3161 + pOta->pTargetFd = p; 3162 + p->pOta = pOta; 3163 + if( p->pWalFd ) p->pWalFd->pOta = pOta; 3164 + rc = SQLITE_OK; 3165 + } 3166 + } 3167 + return rc; 3168 + } 3169 + 3170 + rc = xControl(p->pReal, op, pArg); 3171 + if( rc==SQLITE_OK && op==SQLITE_FCNTL_VFSNAME ){ 3172 + ota_vfs *pOtaVfs = p->pOtaVfs; 3173 + char *zIn = *(char**)pArg; 3174 + char *zOut = sqlite3_mprintf("ota(%s)/%z", pOtaVfs->base.zName, zIn); 3175 + *(char**)pArg = zOut; 3176 + if( zOut==0 ) rc = SQLITE_NOMEM; 3177 + } 3178 + 3179 + return rc; 3180 +} 3181 + 3182 +/* 3183 +** Return the sector-size in bytes for an otaVfs-file. 3184 +*/ 3185 +static int otaVfsSectorSize(sqlite3_file *pFile){ 3186 + ota_file *p = (ota_file *)pFile; 3187 + return p->pReal->pMethods->xSectorSize(p->pReal); 3188 +} 3189 + 3190 +/* 3191 +** Return the device characteristic flags supported by an otaVfs-file. 3192 +*/ 3193 +static int otaVfsDeviceCharacteristics(sqlite3_file *pFile){ 3194 + ota_file *p = (ota_file *)pFile; 3195 + return p->pReal->pMethods->xDeviceCharacteristics(p->pReal); 3196 +} 3197 + 3198 +/* 3199 +** Take or release a shared-memory lock. 3200 +*/ 3201 +static int otaVfsShmLock(sqlite3_file *pFile, int ofst, int n, int flags){ 3202 + ota_file *p = (ota_file*)pFile; 3203 + sqlite3ota *pOta = p->pOta; 3204 + int rc = SQLITE_OK; 3205 + 3206 +#ifdef SQLITE_AMALGAMATION 3207 + assert( WAL_CKPT_LOCK==1 ); 3208 +#endif 3209 + 3210 + assert( p->openFlags & (SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_TEMP_DB) ); 3211 + if( pOta && (pOta->eStage==OTA_STAGE_OAL || pOta->eStage==OTA_STAGE_MOVE) ){ 3212 + /* Magic number 1 is the WAL_CKPT_LOCK lock. Preventing SQLite from 3213 + ** taking this lock also prevents any checkpoints from occurring. 3214 + ** todo: really, it's not clear why this might occur, as 3215 + ** wal_autocheckpoint ought to be turned off. */ 3216 + if( ofst==WAL_LOCK_CKPT && n==1 ) rc = SQLITE_BUSY; 3217 + }else{ 3218 + int bCapture = 0; 3219 + if( n==1 && (flags & SQLITE_SHM_EXCLUSIVE) 3220 + && pOta && pOta->eStage==OTA_STAGE_CAPTURE 3221 + && (ofst==WAL_LOCK_WRITE || ofst==WAL_LOCK_CKPT || ofst==WAL_LOCK_READ0) 3222 + ){ 3223 + bCapture = 1; 3224 + } 3225 + 3226 + if( bCapture==0 || 0==(flags & SQLITE_SHM_UNLOCK) ){ 3227 + rc = p->pReal->pMethods->xShmLock(p->pReal, ofst, n, flags); 3228 + if( bCapture && rc==SQLITE_OK ){ 3229 + pOta->mLock |= (1 << ofst); 3230 + } 3231 + } 3232 + } 3233 + 3234 + return rc; 3235 +} 3236 + 3237 +/* 3238 +** Obtain a pointer to a mapping of a single 32KiB page of the *-shm file. 3239 +*/ 3240 +static int otaVfsShmMap( 3241 + sqlite3_file *pFile, 3242 + int iRegion, 3243 + int szRegion, 3244 + int isWrite, 3245 + void volatile **pp 3246 +){ 3247 + ota_file *p = (ota_file*)pFile; 3248 + int rc = SQLITE_OK; 3249 + int eStage = (p->pOta ? p->pOta->eStage : 0); 3250 + 3251 + /* If not in OTA_STAGE_OAL, allow this call to pass through. Or, if this 3252 + ** ota is in the OTA_STAGE_OAL state, use heap memory for *-shm space 3253 + ** instead of a file on disk. */ 3254 + assert( p->openFlags & (SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_TEMP_DB) ); 3255 + if( eStage==OTA_STAGE_OAL || eStage==OTA_STAGE_MOVE ){ 3256 + if( iRegion<=p->nShm ){ 3257 + int nByte = (iRegion+1) * sizeof(char*); 3258 + char **apNew = (char**)sqlite3_realloc(p->apShm, nByte); 3259 + if( apNew==0 ){ 3260 + rc = SQLITE_NOMEM; 3261 + }else{ 3262 + memset(&apNew[p->nShm], 0, sizeof(char*) * (1 + iRegion - p->nShm)); 3263 + p->apShm = apNew; 3264 + p->nShm = iRegion+1; 3265 + } 3266 + } 3267 + 3268 + if( rc==SQLITE_OK && p->apShm[iRegion]==0 ){ 3269 + char *pNew = (char*)sqlite3_malloc(szRegion); 3270 + if( pNew==0 ){ 3271 + rc = SQLITE_NOMEM; 3272 + }else{ 3273 + memset(pNew, 0, szRegion); 3274 + p->apShm[iRegion] = pNew; 3275 + } 3276 + } 3277 + 3278 + if( rc==SQLITE_OK ){ 3279 + *pp = p->apShm[iRegion]; 3280 + }else{ 3281 + *pp = 0; 3282 + } 3283 + }else{ 3284 + assert( p->apShm==0 ); 3285 + rc = p->pReal->pMethods->xShmMap(p->pReal, iRegion, szRegion, isWrite, pp); 3286 + } 3287 + 3288 + return rc; 3289 +} 3290 + 3291 +/* 3292 +** Memory barrier. 3293 +*/ 3294 +static void otaVfsShmBarrier(sqlite3_file *pFile){ 3295 + ota_file *p = (ota_file *)pFile; 3296 + p->pReal->pMethods->xShmBarrier(p->pReal); 3297 +} 3298 + 3299 +/* 3300 +** The xShmUnmap method. 3301 +*/ 3302 +static int otaVfsShmUnmap(sqlite3_file *pFile, int delFlag){ 3303 + ota_file *p = (ota_file*)pFile; 3304 + int rc = SQLITE_OK; 3305 + int eStage = (p->pOta ? p->pOta->eStage : 0); 3306 + 3307 + assert( p->openFlags & (SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_TEMP_DB) ); 3308 + if( eStage==OTA_STAGE_OAL || eStage==OTA_STAGE_MOVE ){ 3309 + /* no-op */ 3310 + }else{ 3311 + /* Release the checkpointer and writer locks */ 3312 + otaUnlockShm(p); 3313 + rc = p->pReal->pMethods->xShmUnmap(p->pReal, delFlag); 3314 + } 3315 + return rc; 3316 +} 3317 + 3318 +/* 3319 +** Given that zWal points to a buffer containing a wal file name passed to 3320 +** either the xOpen() or xAccess() VFS method, return a pointer to the 3321 +** file-handle opened by the same database connection on the corresponding 3322 +** database file. 3323 +*/ 3324 +static ota_file *otaFindMaindb(ota_vfs *pOtaVfs, const char *zWal){ 3325 + ota_file *pDb; 3326 + sqlite3_mutex_enter(pOtaVfs->mutex); 3327 + for(pDb=pOtaVfs->pMain; pDb && pDb->zWal!=zWal; pDb=pDb->pMainNext); 3328 + sqlite3_mutex_leave(pOtaVfs->mutex); 3329 + return pDb; 3330 +} 3331 + 3332 +/* 3333 +** Open an ota file handle. 3334 +*/ 3335 +static int otaVfsOpen( 3336 + sqlite3_vfs *pVfs, 3337 + const char *zName, 3338 + sqlite3_file *pFile, 3339 + int flags, 3340 + int *pOutFlags 3341 +){ 3342 + static sqlite3_io_methods otavfs_io_methods = { 3343 + 2, /* iVersion */ 3344 + otaVfsClose, /* xClose */ 3345 + otaVfsRead, /* xRead */ 3346 + otaVfsWrite, /* xWrite */ 3347 + otaVfsTruncate, /* xTruncate */ 3348 + otaVfsSync, /* xSync */ 3349 + otaVfsFileSize, /* xFileSize */ 3350 + otaVfsLock, /* xLock */ 3351 + otaVfsUnlock, /* xUnlock */ 3352 + otaVfsCheckReservedLock, /* xCheckReservedLock */ 3353 + otaVfsFileControl, /* xFileControl */ 3354 + otaVfsSectorSize, /* xSectorSize */ 3355 + otaVfsDeviceCharacteristics, /* xDeviceCharacteristics */ 3356 + otaVfsShmMap, /* xShmMap */ 3357 + otaVfsShmLock, /* xShmLock */ 3358 + otaVfsShmBarrier, /* xShmBarrier */ 3359 + otaVfsShmUnmap /* xShmUnmap */ 3360 + }; 3361 + ota_vfs *pOtaVfs = (ota_vfs*)pVfs; 3362 + sqlite3_vfs *pRealVfs = pOtaVfs->pRealVfs; 3363 + ota_file *pFd = (ota_file *)pFile; 3364 + int rc = SQLITE_OK; 3365 + const char *zOpen = zName; 3366 + 3367 + memset(pFd, 0, sizeof(ota_file)); 3368 + pFd->pReal = (sqlite3_file*)&pFd[1]; 3369 + pFd->pOtaVfs = pOtaVfs; 3370 + pFd->openFlags = flags; 3371 + if( zName ){ 3372 + if( flags & SQLITE_OPEN_MAIN_DB ){ 3373 + /* A main database has just been opened. The following block sets 3374 + ** (pFd->zWal) to point to a buffer owned by SQLite that contains 3375 + ** the name of the *-wal file this db connection will use. SQLite 3376 + ** happens to pass a pointer to this buffer when using xAccess() 3377 + ** or xOpen() to operate on the *-wal file. */ 3378 + int n = strlen(zName); 3379 + const char *z = &zName[n]; 3380 + if( flags & SQLITE_OPEN_URI ){ 3381 + int odd = 0; 3382 + while( 1 ){ 3383 + if( z[0]==0 ){ 3384 + odd = 1 - odd; 3385 + if( odd && z[1]==0 ) break; 3386 + } 3387 + z++; 3388 + } 3389 + z += 2; 3390 + }else{ 3391 + while( *z==0 ) z++; 3392 + } 3393 + z += (n + 8 + 1); 3394 + pFd->zWal = z; 3395 + } 3396 + else if( flags & SQLITE_OPEN_WAL ){ 3397 + ota_file *pDb = otaFindMaindb(pOtaVfs, zName); 3398 + if( pDb ){ 3399 + if( pDb->pOta && pDb->pOta->eStage==OTA_STAGE_OAL ){ 3400 + /* This call is to open a *-wal file. Intead, open the *-oal. This 3401 + ** code ensures that the string passed to xOpen() is terminated by a 3402 + ** pair of '\0' bytes in case the VFS attempts to extract a URI 3403 + ** parameter from it. */ 3404 + int nCopy = strlen(zName); 3405 + char *zCopy = sqlite3_malloc(nCopy+2); 3406 + if( zCopy ){ 3407 + memcpy(zCopy, zName, nCopy); 3408 + zCopy[nCopy-3] = 'o'; 3409 + zCopy[nCopy] = '\0'; 3410 + zCopy[nCopy+1] = '\0'; 3411 + zOpen = (const char*)(pFd->zDel = zCopy); 3412 + }else{ 3413 + rc = SQLITE_NOMEM; 3414 + } 3415 + pFd->pOta = pDb->pOta; 3416 + } 3417 + pDb->pWalFd = pFd; 3418 + } 3419 + } 3420 + } 3421 + 3422 + if( rc==SQLITE_OK ){ 3423 + rc = pRealVfs->xOpen(pRealVfs, zOpen, pFd->pReal, flags, pOutFlags); 3424 + } 3425 + if( pFd->pReal->pMethods ){ 3426 + /* The xOpen() operation has succeeded. Set the sqlite3_file.pMethods 3427 + ** pointer and, if the file is a main database file, link it into the 3428 + ** mutex protected linked list of all such files. */ 3429 + pFile->pMethods = &otavfs_io_methods; 3430 + if( flags & SQLITE_OPEN_MAIN_DB ){ 3431 + sqlite3_mutex_enter(pOtaVfs->mutex); 3432 + pFd->pMainNext = pOtaVfs->pMain; 3433 + pOtaVfs->pMain = pFd; 3434 + sqlite3_mutex_leave(pOtaVfs->mutex); 3435 + } 3436 + }else{ 3437 + sqlite3_free(pFd->zDel); 3438 + } 3439 + 3440 + return rc; 3441 +} 3442 + 3443 +/* 3444 +** Delete the file located at zPath. 3445 +*/ 3446 +static int otaVfsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ 3447 + sqlite3_vfs *pRealVfs = ((ota_vfs*)pVfs)->pRealVfs; 3448 + return pRealVfs->xDelete(pRealVfs, zPath, dirSync); 3449 +} 3450 + 3451 +/* 3452 +** Test for access permissions. Return true if the requested permission 3453 +** is available, or false otherwise. 3454 +*/ 3455 +static int otaVfsAccess( 3456 + sqlite3_vfs *pVfs, 3457 + const char *zPath, 3458 + int flags, 3459 + int *pResOut 3460 +){ 3461 + ota_vfs *pOtaVfs = (ota_vfs*)pVfs; 3462 + sqlite3_vfs *pRealVfs = pOtaVfs->pRealVfs; 3463 + int rc; 3464 + 3465 + rc = pRealVfs->xAccess(pRealVfs, zPath, flags, pResOut); 3466 + 3467 + /* If this call is to check if a *-wal file associated with an OTA target 3468 + ** database connection exists, and the OTA update is in OTA_STAGE_OAL, 3469 + ** the following special handling is activated: 3470 + ** 3471 + ** a) if the *-wal file does exist, return SQLITE_CANTOPEN. This 3472 + ** ensures that the OTA extension never tries to update a database 3473 + ** in wal mode, even if the first page of the database file has 3474 + ** been damaged. 3475 + ** 3476 + ** b) if the *-wal file does not exist, claim that it does anyway, 3477 + ** causing SQLite to call xOpen() to open it. This call will also 3478 + ** be intercepted (see the otaVfsOpen() function) and the *-oal 3479 + ** file opened instead. 3480 + */ 3481 + if( rc==SQLITE_OK && flags==SQLITE_ACCESS_EXISTS ){ 3482 + ota_file *pDb = otaFindMaindb(pOtaVfs, zPath); 3483 + if( pDb && pDb->pOta && pDb->pOta->eStage==OTA_STAGE_OAL ){ 3484 + if( *pResOut ){ 3485 + rc = SQLITE_CANTOPEN; 3486 + }else{ 3487 + *pResOut = 1; 3488 + } 3489 + } 3490 + } 3491 + 3492 + return rc; 3493 +} 3494 + 3495 +/* 3496 +** Populate buffer zOut with the full canonical pathname corresponding 3497 +** to the pathname in zPath. zOut is guaranteed to point to a buffer 3498 +** of at least (DEVSYM_MAX_PATHNAME+1) bytes. 3499 +*/ 3500 +static int otaVfsFullPathname( 3501 + sqlite3_vfs *pVfs, 3502 + const char *zPath, 3503 + int nOut, 3504 + char *zOut 3505 +){ 3506 + sqlite3_vfs *pRealVfs = ((ota_vfs*)pVfs)->pRealVfs; 3507 + return pRealVfs->xFullPathname(pRealVfs, zPath, nOut, zOut); 3508 +} 3509 + 3510 +#ifndef SQLITE_OMIT_LOAD_EXTENSION 3511 +/* 3512 +** Open the dynamic library located at zPath and return a handle. 3513 +*/ 3514 +static void *otaVfsDlOpen(sqlite3_vfs *pVfs, const char *zPath){ 3515 + sqlite3_vfs *pRealVfs = ((ota_vfs*)pVfs)->pRealVfs; 3516 + return pRealVfs->xDlOpen(pRealVfs, zPath); 3517 +} 3518 + 3519 +/* 3520 +** Populate the buffer zErrMsg (size nByte bytes) with a human readable 3521 +** utf-8 string describing the most recent error encountered associated 3522 +** with dynamic libraries. 3523 +*/ 3524 +static void otaVfsDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){ 3525 + sqlite3_vfs *pRealVfs = ((ota_vfs*)pVfs)->pRealVfs; 3526 + pRealVfs->xDlError(pRealVfs, nByte, zErrMsg); 3527 +} 3528 + 3529 +/* 3530 +** Return a pointer to the symbol zSymbol in the dynamic library pHandle. 3531 +*/ 3532 +static void (*otaVfsDlSym( 3533 + sqlite3_vfs *pVfs, 3534 + void *pArg, 3535 + const char *zSym 3536 +))(void){ 3537 + sqlite3_vfs *pRealVfs = ((ota_vfs*)pVfs)->pRealVfs; 3538 + return pRealVfs->xDlSym(pRealVfs, pArg, zSym); 3539 +} 3540 + 3541 +/* 3542 +** Close the dynamic library handle pHandle. 3543 +*/ 3544 +static void otaVfsDlClose(sqlite3_vfs *pVfs, void *pHandle){ 3545 + sqlite3_vfs *pRealVfs = ((ota_vfs*)pVfs)->pRealVfs; 3546 + return pRealVfs->xDlClose(pRealVfs, pHandle); 3547 +} 3548 +#endif /* SQLITE_OMIT_LOAD_EXTENSION */ 3549 + 3550 +/* 3551 +** Populate the buffer pointed to by zBufOut with nByte bytes of 3552 +** random data. 3553 +*/ 3554 +static int otaVfsRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){ 3555 + sqlite3_vfs *pRealVfs = ((ota_vfs*)pVfs)->pRealVfs; 3556 + return pRealVfs->xRandomness(pRealVfs, nByte, zBufOut); 3557 +} 3558 + 3559 +/* 3560 +** Sleep for nMicro microseconds. Return the number of microseconds 3561 +** actually slept. 3562 +*/ 3563 +static int otaVfsSleep(sqlite3_vfs *pVfs, int nMicro){ 3564 + sqlite3_vfs *pRealVfs = ((ota_vfs*)pVfs)->pRealVfs; 3565 + return pRealVfs->xSleep(pRealVfs, nMicro); 3566 +} 3567 + 3568 +/* 3569 +** Return the current time as a Julian Day number in *pTimeOut. 3570 +*/ 3571 +static int otaVfsCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){ 3572 + sqlite3_vfs *pRealVfs = ((ota_vfs*)pVfs)->pRealVfs; 3573 + return pRealVfs->xCurrentTime(pRealVfs, pTimeOut); 3574 +} 3575 + 3576 +/* 3577 +** No-op. 3578 +*/ 3579 +static int otaVfsGetLastError(sqlite3_vfs *pVfs, int a, char *b){ 3580 + return 0; 3581 +} 3582 + 3583 +/* 3584 +** Deregister and destroy an OTA vfs created by an earlier call to 3585 +** sqlite3ota_create_vfs(). 3586 +*/ 3587 +void sqlite3ota_destroy_vfs(const char *zName){ 3588 + sqlite3_vfs *pVfs = sqlite3_vfs_find(zName); 3589 + if( pVfs && pVfs->xOpen==otaVfsOpen ){ 3590 + sqlite3_mutex_free(((ota_vfs*)pVfs)->mutex); 3591 + sqlite3_vfs_unregister(pVfs); 3592 + sqlite3_free(pVfs); 3593 + } 3594 +} 3595 + 3596 +/* 3597 +** Create an OTA VFS named zName that accesses the underlying file-system 3598 +** via existing VFS zParent. The new object is registered as a non-default 3599 +** VFS with SQLite before returning. 3600 +*/ 3601 +int sqlite3ota_create_vfs(const char *zName, const char *zParent){ 3602 + 3603 + /* Template for VFS */ 3604 + static sqlite3_vfs vfs_template = { 3605 + 1, /* iVersion */ 3606 + 0, /* szOsFile */ 3607 + 0, /* mxPathname */ 3608 + 0, /* pNext */ 3609 + 0, /* zName */ 3610 + 0, /* pAppData */ 3611 + otaVfsOpen, /* xOpen */ 3612 + otaVfsDelete, /* xDelete */ 3613 + otaVfsAccess, /* xAccess */ 3614 + otaVfsFullPathname, /* xFullPathname */ 3615 + 3616 +#ifndef SQLITE_OMIT_LOAD_EXTENSION 3617 + otaVfsDlOpen, /* xDlOpen */ 3618 + otaVfsDlError, /* xDlError */ 3619 + otaVfsDlSym, /* xDlSym */ 3620 + otaVfsDlClose, /* xDlClose */ 3621 +#else 3622 + 0, 0, 0, 0, 3623 +#endif 3624 + 3625 + otaVfsRandomness, /* xRandomness */ 3626 + otaVfsSleep, /* xSleep */ 3627 + otaVfsCurrentTime, /* xCurrentTime */ 3628 + otaVfsGetLastError, /* xGetLastError */ 3629 + 0, /* xCurrentTimeInt64 (version 2) */ 3630 + 0, 0, 0 /* Unimplemented version 3 methods */ 3631 + }; 3632 + 3633 + ota_vfs *pNew = 0; /* Newly allocated VFS */ 3634 + int nName; 3635 + int rc = SQLITE_OK; 3636 + 3637 + int nByte; 3638 + nName = strlen(zName); 3639 + nByte = sizeof(ota_vfs) + nName + 1; 3640 + pNew = (ota_vfs*)sqlite3_malloc(nByte); 3641 + if( pNew==0 ){ 3642 + rc = SQLITE_NOMEM; 3643 + }else{ 3644 + sqlite3_vfs *pParent; /* Parent VFS */ 3645 + memset(pNew, 0, nByte); 3646 + pParent = sqlite3_vfs_find(zParent); 3647 + if( pParent==0 ){ 3648 + rc = SQLITE_NOTFOUND; 3649 + }else{ 3650 + char *zSpace; 3651 + memcpy(&pNew->base, &vfs_template, sizeof(sqlite3_vfs)); 3652 + pNew->base.mxPathname = pParent->mxPathname; 3653 + pNew->base.szOsFile = sizeof(ota_file) + pParent->szOsFile; 3654 + pNew->pRealVfs = pParent; 3655 + pNew->base.zName = (const char*)(zSpace = (char*)&pNew[1]); 3656 + memcpy(zSpace, zName, nName); 3657 + 3658 + /* Allocate the mutex and register the new VFS (not as the default) */ 3659 + pNew->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_RECURSIVE); 3660 + if( pNew->mutex==0 ){ 3661 + rc = SQLITE_NOMEM; 3662 + }else{ 3663 + rc = sqlite3_vfs_register(&pNew->base, 0); 3664 + } 3665 + } 3666 + 3667 + if( rc!=SQLITE_OK ){ 3668 + sqlite3_mutex_free(pNew->mutex); 3669 + sqlite3_free(pNew); 3670 + } 3671 + } 3672 + 3673 + return rc; 3674 +} 3675 + 3676 + 3677 +/**************************************************************************/ 3678 + 3679 +#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_OTA) */
Added ext/ota/sqlite3ota.h.
1 +/* 2 +** 2014 August 30 3 +** 4 +** The author disclaims copyright to this source code. In place of 5 +** a legal notice, here is a blessing: 6 +** 7 +** May you do good and not evil. 8 +** May you find forgiveness for yourself and forgive others. 9 +** May you share freely, never taking more than you give. 10 +** 11 +************************************************************************* 12 +** 13 +** This file contains the public interface for the OTA extension. 14 +*/ 15 + 16 +/* 17 +** SUMMARY 18 +** 19 +** Writing a transaction containing a large number of operations on 20 +** b-tree indexes that are collectively larger than the available cache 21 +** memory can be very inefficient. 22 +** 23 +** The problem is that in order to update a b-tree, the leaf page (at least) 24 +** containing the entry being inserted or deleted must be modified. If the 25 +** working set of leaves is larger than the available cache memory, then a 26 +** single leaf that is modified more than once as part of the transaction 27 +** may be loaded from or written to the persistent media multiple times. 28 +** Additionally, because the index updates are likely to be applied in 29 +** random order, access to pages within the database is also likely to be in 30 +** random order, which is itself quite inefficient. 31 +** 32 +** One way to improve the situation is to sort the operations on each index 33 +** by index key before applying them to the b-tree. This leads to an IO 34 +** pattern that resembles a single linear scan through the index b-tree, 35 +** and all but guarantees each modified leaf page is loaded and stored 36 +** exactly once. SQLite uses this trick to improve the performance of 37 +** CREATE INDEX commands. This extension allows it to be used to improve 38 +** the performance of large transactions on existing databases. 39 +** 40 +** Additionally, this extension allows the work involved in writing the 41 +** large transaction to be broken down into sub-transactions performed 42 +** sequentially by separate processes. This is useful if the system cannot 43 +** guarantee that a single update process will run for long enough to apply 44 +** the entire update, for example because the update is being applied on a 45 +** mobile device that is frequently rebooted. Even after the writer process 46 +** has committed one or more sub-transactions, other database clients continue 47 +** to read from the original database snapshot. In other words, partially 48 +** applied transactions are not visible to other clients. 49 +** 50 +** "OTA" stands for "Over The Air" update. As in a large database update 51 +** transmitted via a wireless network to a mobile device. A transaction 52 +** applied using this extension is hence refered to as an "OTA update". 53 +** 54 +** 55 +** LIMITATIONS 56 +** 57 +** An "OTA update" transaction is subject to the following limitations: 58 +** 59 +** * The transaction must consist of INSERT, UPDATE and DELETE operations 60 +** only. 61 +** 62 +** * INSERT statements may not use any default values. 63 +** 64 +** * UPDATE and DELETE statements must identify their target rows by 65 +** non-NULL PRIMARY KEY values. Rows with NULL values stored in PRIMARY 66 +** KEY fields may not be updated or deleted. If the table being written 67 +** has no PRIMARY KEY, affected rows must be identified by rowid. 68 +** 69 +** * UPDATE statements may not modify PRIMARY KEY columns. 70 +** 71 +** * No triggers will be fired. 72 +** 73 +** * No foreign key violations are detected or reported. 74 +** 75 +** * CHECK constraints are not enforced. 76 +** 77 +** * No constraint handling mode except for "OR ROLLBACK" is supported. 78 +** 79 +** 80 +** PREPARATION 81 +** 82 +** An "OTA update" is stored as a separate SQLite database. A database 83 +** containing an OTA update is an "OTA database". For each table in the 84 +** target database to be updated, the OTA database should contain a table 85 +** named "data_<target name>" containing the same set of columns as the 86 +** target table, and one more - "ota_control". The data_% table should 87 +** have no PRIMARY KEY or UNIQUE constraints, but each column should have 88 +** the same type as the corresponding column in the target database. 89 +** The "ota_control" column should have no type at all. For example, if 90 +** the target database contains: 91 +** 92 +** CREATE TABLE t1(a INTEGER PRIMARY KEY, b TEXT, c UNIQUE); 93 +** 94 +** Then the OTA database should contain: 95 +** 96 +** CREATE TABLE data_t1(a INTEGER, b TEXT, c, ota_control); 97 +** 98 +** The order of the columns in the data_% table does not matter. 99 +** 100 +** If the target database table is a virtual table or a table that has no 101 +** PRIMARY KEY declaration, the data_% table must also contain a column 102 +** named "ota_rowid". This column is mapped to the tables implicit primary 103 +** key column - "rowid". Virtual tables for which the "rowid" column does 104 +** not function like a primary key value cannot be updated using OTA. For 105 +** example, if the target db contains either of the following: 106 +** 107 +** CREATE VIRTUAL TABLE x1 USING fts3(a, b); 108 +** CREATE TABLE x1(a, b) 109 +** 110 +** then the OTA database should contain: 111 +** 112 +** CREATE TABLE data_x1(a, b, ota_rowid, ota_control); 113 +** 114 +** All non-hidden columns (i.e. all columns matched by "SELECT *") of the 115 +** target table must be present in the input table. For virtual tables, 116 +** hidden columns are optional - they are updated by OTA if present in 117 +** the input table, or not otherwise. For example, to write to an fts4 118 +** table with a hidden languageid column such as: 119 +** 120 +** CREATE VIRTUAL TABLE ft1 USING fts4(a, b, languageid='langid'); 121 +** 122 +** Either of the following input table schemas may be used: 123 +** 124 +** CREATE TABLE data_ft1(a, b, langid, ota_rowid, ota_control); 125 +** CREATE TABLE data_ft1(a, b, ota_rowid, ota_control); 126 +** 127 +** For each row to INSERT into the target database as part of the OTA 128 +** update, the corresponding data_% table should contain a single record 129 +** with the "ota_control" column set to contain integer value 0. The 130 +** other columns should be set to the values that make up the new record 131 +** to insert. 132 +** 133 +** If the target database table has an INTEGER PRIMARY KEY, it is not 134 +** possible to insert a NULL value into the IPK column. Attempting to 135 +** do so results in an SQLITE_MISMATCH error. 136 +** 137 +** For each row to DELETE from the target database as part of the OTA 138 +** update, the corresponding data_% table should contain a single record 139 +** with the "ota_control" column set to contain integer value 1. The 140 +** real primary key values of the row to delete should be stored in the 141 +** corresponding columns of the data_% table. The values stored in the 142 +** other columns are not used. 143 +** 144 +** For each row to UPDATE from the target database as part of the OTA 145 +** update, the corresponding data_% table should contain a single record 146 +** with the "ota_control" column set to contain a value of type text. 147 +** The real primary key values identifying the row to update should be 148 +** stored in the corresponding columns of the data_% table row, as should 149 +** the new values of all columns being update. The text value in the 150 +** "ota_control" column must contain the same number of characters as 151 +** there are columns in the target database table, and must consist entirely 152 +** of 'x' and '.' characters (or in some special cases 'd' - see below). For 153 +** each column that is being updated, the corresponding character is set to 154 +** 'x'. For those that remain as they are, the corresponding character of the 155 +** ota_control value should be set to '.'. For example, given the tables 156 +** above, the update statement: 157 +** 158 +** UPDATE t1 SET c = 'usa' WHERE a = 4; 159 +** 160 +** is represented by the data_t1 row created by: 161 +** 162 +** INSERT INTO data_t1(a, b, c, ota_control) VALUES(4, NULL, 'usa', '..x'); 163 +** 164 +** Instead of an 'x' character, characters of the ota_control value specified 165 +** for UPDATEs may also be set to 'd'. In this case, instead of updating the 166 +** target table with the value stored in the corresponding data_% column, the 167 +** user-defined SQL function "ota_delta()" is invoked and the result stored in 168 +** the target table column. ota_delta() is invoked with two arguments - the 169 +** original value currently stored in the target table column and the 170 +** value specified in the data_xxx table. 171 +** 172 +** For example, this row: 173 +** 174 +** INSERT INTO data_t1(a, b, c, ota_control) VALUES(4, NULL, 'usa', '..d'); 175 +** 176 +** is similar to an UPDATE statement such as: 177 +** 178 +** UPDATE t1 SET c = ota_delta(c, 'usa') WHERE a = 4; 179 +** 180 +** If the target database table is a virtual table or a table with no PRIMARY 181 +** KEY, the ota_control value should not include a character corresponding 182 +** to the ota_rowid value. For example, this: 183 +** 184 +** INSERT INTO data_ft1(a, b, ota_rowid, ota_control) 185 +** VALUES(NULL, 'usa', 12, '.x'); 186 +** 187 +** causes a result similar to: 188 +** 189 +** UPDATE ft1 SET b = 'usa' WHERE rowid = 12; 190 +** 191 +** The data_xxx tables themselves should have no PRIMARY KEY declarations. 192 +** However, OTA is more efficient if reading the rows in from each data_xxx 193 +** table in "rowid" order is roughly the same as reading them sorted by 194 +** the PRIMARY KEY of the corresponding target database table. In other 195 +** words, rows should be sorted using the destination table PRIMARY KEY 196 +** fields before they are inserted into the data_xxx tables. 197 +** 198 +** USAGE 199 +** 200 +** The API declared below allows an application to apply an OTA update 201 +** stored on disk to an existing target database. Essentially, the 202 +** application: 203 +** 204 +** 1) Opens an OTA handle using the sqlite3ota_open() function. 205 +** 206 +** 2) Registers any required virtual table modules with the database 207 +** handle returned by sqlite3ota_db(). Also, if required, register 208 +** the ota_delta() implementation. 209 +** 210 +** 3) Calls the sqlite3ota_step() function one or more times on 211 +** the new handle. Each call to sqlite3ota_step() performs a single 212 +** b-tree operation, so thousands of calls may be required to apply 213 +** a complete update. 214 +** 215 +** 4) Calls sqlite3ota_close() to close the OTA update handle. If 216 +** sqlite3ota_step() has been called enough times to completely 217 +** apply the update to the target database, then the OTA database 218 +** is marked as fully applied. Otherwise, the state of the OTA 219 +** update application is saved in the OTA database for later 220 +** resumption. 221 +** 222 +** See comments below for more detail on APIs. 223 +** 224 +** If an update is only partially applied to the target database by the 225 +** time sqlite3ota_close() is called, various state information is saved 226 +** within the OTA database. This allows subsequent processes to automatically 227 +** resume the OTA update from where it left off. 228 +** 229 +** To remove all OTA extension state information, returning an OTA database 230 +** to its original contents, it is sufficient to drop all tables that begin 231 +** with the prefix "ota_" 232 +** 233 +** DATABASE LOCKING 234 +** 235 +** An OTA update may not be applied to a database in WAL mode. Attempting 236 +** to do so is an error (SQLITE_ERROR). 237 +** 238 +** While an OTA handle is open, a SHARED lock may be held on the target 239 +** database file. This means it is possible for other clients to read the 240 +** database, but not to write it. 241 +** 242 +** If an OTA update is started and then suspended before it is completed, 243 +** then an external client writes to the database, then attempting to resume 244 +** the suspended OTA update is also an error (SQLITE_BUSY). 245 +*/ 246 + 247 +#ifndef _SQLITE3OTA_H 248 +#define _SQLITE3OTA_H 249 + 250 +#include "sqlite3.h" /* Required for error code definitions */ 251 + 252 +typedef struct sqlite3ota sqlite3ota; 253 + 254 +/* 255 +** Open an OTA handle. 256 +** 257 +** Argument zTarget is the path to the target database. Argument zOta is 258 +** the path to the OTA database. Each call to this function must be matched 259 +** by a call to sqlite3ota_close(). When opening the databases, OTA passes 260 +** the SQLITE_CONFIG_URI flag to sqlite3_open_v2(). So if either zTarget 261 +** or zOta begin with "file:", it will be interpreted as an SQLite 262 +** database URI, not a regular file name. 263 +** 264 +** By default, OTA uses the default VFS to access the files on disk. To 265 +** use a VFS other than the default, an SQLite "file:" URI containing a 266 +** "vfs=..." option may be passed as the zTarget option. 267 +** 268 +** IMPORTANT NOTE FOR ZIPVFS USERS: The OTA extension works with all of 269 +** SQLite's built-in VFSs, including the multiplexor VFS. However it does 270 +** not work out of the box with zipvfs. Refer to the comment describing 271 +** the zipvfs_create_vfs() API below for details on using OTA with zipvfs. 272 +*/ 273 +sqlite3ota *sqlite3ota_open(const char *zTarget, const char *zOta); 274 + 275 +/* 276 +** Open an OTA handle with an auxiliary state file. 277 +** 278 +** This API is similar to sqlite3ota_open(), except that it allows the user 279 +** to specify a separate SQLite database in which to store the OTA update 280 +** state. 281 +** 282 +** While executing, the OTA extension usually stores the current state 283 +** of the update (how many rows have been updated, which indexes are yet 284 +** to be updated etc.) within the OTA database itself. This can be 285 +** convenient, as it means that the OTA application does not need to 286 +** organize removing a separate state file after the update is concluded. 287 +** However, it can also be inconvenient - for example if the OTA update 288 +** database is sto be stored on a read-only media. 289 +** 290 +** If an OTA update started using a handle opened with this function is 291 +** suspended, the application must use this function to resume it, and 292 +** must pass the same zState argument each time the update is resumed. 293 +** Attempting to resume an sqlite3ota_open_v2() update using sqlite3ota_open(), 294 +** or with a call to sqlite3ota_open_v2() specifying a different zState 295 +** argument leads to undefined behaviour. 296 +** 297 +** Once the OTA update is finished, the OTA extension does not 298 +** automatically remove the zState database file, even if it created it. 299 +*/ 300 +sqlite3ota *sqlite3ota_open_v2( 301 + const char *zTarget, 302 + const char *zOta, 303 + const char *zState 304 +); 305 + 306 +/* 307 +** Internally, each OTA connection uses a separate SQLite database 308 +** connection to access the target and ota update databases. This 309 +** API allows the application direct access to these database handles. 310 +** 311 +** The first argument passed to this function must be a valid, open, OTA 312 +** handle. The second argument should be passed zero to access the target 313 +** database handle, or non-zero to access the ota update database handle. 314 +** Accessing the underlying database handles may be useful in the 315 +** following scenarios: 316 +** 317 +** * If any target tables are virtual tables, it may be necessary to 318 +** call sqlite3_create_module() on the target database handle to 319 +** register the required virtual table implementations. 320 +** 321 +** * If the data_xxx tables in the OTA source database are virtual 322 +** tables, the application may need to call sqlite3_create_module() on 323 +** the ota update db handle to any required virtual table 324 +** implementations. 325 +** 326 +** * If the application uses the "ota_delta()" feature described above, 327 +** it must use sqlite3_create_function() or similar to register the 328 +** ota_delta() implementation with the target database handle. 329 +** 330 +** If an error has occurred, either while opening or stepping the OTA object, 331 +** this function may return NULL. The error code and message may be collected 332 +** when sqlite3ota_close() is called. 333 +*/ 334 +sqlite3 *sqlite3ota_db(sqlite3ota*, int bOta); 335 + 336 +/* 337 +** Do some work towards applying the OTA update to the target db. 338 +** 339 +** Return SQLITE_DONE if the update has been completely applied, or 340 +** SQLITE_OK if no error occurs but there remains work to do to apply 341 +** the OTA update. If an error does occur, some other error code is 342 +** returned. 343 +** 344 +** Once a call to sqlite3ota_step() has returned a value other than 345 +** SQLITE_OK, all subsequent calls on the same OTA handle are no-ops 346 +** that immediately return the same value. 347 +*/ 348 +int sqlite3ota_step(sqlite3ota *pOta); 349 + 350 +/* 351 +** Close an OTA handle. 352 +** 353 +** If the OTA update has been completely applied, mark the OTA database 354 +** as fully applied. Otherwise, assuming no error has occurred, save the 355 +** current state of the OTA update appliation to the OTA database. 356 +** 357 +** If an error has already occurred as part of an sqlite3ota_step() 358 +** or sqlite3ota_open() call, or if one occurs within this function, an 359 +** SQLite error code is returned. Additionally, *pzErrmsg may be set to 360 +** point to a buffer containing a utf-8 formatted English language error 361 +** message. It is the responsibility of the caller to eventually free any 362 +** such buffer using sqlite3_free(). 363 +** 364 +** Otherwise, if no error occurs, this function returns SQLITE_OK if the 365 +** update has been partially applied, or SQLITE_DONE if it has been 366 +** completely applied. 367 +*/ 368 +int sqlite3ota_close(sqlite3ota *pOta, char **pzErrmsg); 369 + 370 +/* 371 +** Return the total number of key-value operations (inserts, deletes or 372 +** updates) that have been performed on the target database since the 373 +** current OTA update was started. 374 +*/ 375 +sqlite3_int64 sqlite3ota_progress(sqlite3ota *pOta); 376 + 377 +/* 378 +** Create an OTA VFS named zName that accesses the underlying file-system 379 +** via existing VFS zParent. Or, if the zParent parameter is passed NULL, 380 +** then the new OTA VFS uses the default system VFS to access the file-system. 381 +** The new object is registered as a non-default VFS with SQLite before 382 +** returning. 383 +** 384 +** Part of the OTA implementation uses a custom VFS object. Usually, this 385 +** object is created and deleted automatically by OTA. 386 +** 387 +** The exception is for applications that also use zipvfs. In this case, 388 +** the custom VFS must be explicitly created by the user before the OTA 389 +** handle is opened. The OTA VFS should be installed so that the zipvfs 390 +** VFS uses the OTA VFS, which in turn uses any other VFS layers in use 391 +** (for example multiplexor) to access the file-system. For example, 392 +** to assemble an OTA enabled VFS stack that uses both zipvfs and 393 +** multiplexor (error checking omitted): 394 +** 395 +** // Create a VFS named "multiplex" (not the default). 396 +** sqlite3_multiplex_initialize(0, 0); 397 +** 398 +** // Create an ota VFS named "ota" that uses multiplexor. If the 399 +** // second argument were replaced with NULL, the "ota" VFS would 400 +** // access the file-system via the system default VFS, bypassing the 401 +** // multiplexor. 402 +** sqlite3ota_create_vfs("ota", "multiplex"); 403 +** 404 +** // Create a zipvfs VFS named "zipvfs" that uses ota. 405 +** zipvfs_create_vfs_v3("zipvfs", "ota", 0, xCompressorAlgorithmDetector); 406 +** 407 +** // Make zipvfs the default VFS. 408 +** sqlite3_vfs_register(sqlite3_vfs_find("zipvfs"), 1); 409 +** 410 +** Because the default VFS created above includes a OTA functionality, it 411 +** may be used by OTA clients. Attempting to use OTA with a zipvfs VFS stack 412 +** that does not include the OTA layer results in an error. 413 +** 414 +** The overhead of adding the "ota" VFS to the system is negligible for 415 +** non-OTA users. There is no harm in an application accessing the 416 +** file-system via "ota" all the time, even if it only uses OTA functionality 417 +** occasionally. 418 +*/ 419 +int sqlite3ota_create_vfs(const char *zName, const char *zParent); 420 + 421 +/* 422 +** Deregister and destroy an OTA vfs created by an earlier call to 423 +** sqlite3ota_create_vfs(). 424 +** 425 +** VFS objects are not reference counted. If a VFS object is destroyed 426 +** before all database handles that use it have been closed, the results 427 +** are undefined. 428 +*/ 429 +void sqlite3ota_destroy_vfs(const char *zName); 430 + 431 +#endif /* _SQLITE3OTA_H */ 432 +
Added ext/ota/test_ota.c.
1 +/* 2 +** 2015 February 16 3 +** 4 +** The author disclaims copyright to this source code. In place of 5 +** a legal notice, here is a blessing: 6 +** 7 +** May you do good and not evil. 8 +** May you find forgiveness for yourself and forgive others. 9 +** May you share freely, never taking more than you give. 10 +** 11 +************************************************************************* 12 +*/ 13 + 14 +#include "sqlite3.h" 15 + 16 +#if defined(SQLITE_TEST) 17 +#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_OTA) 18 + 19 +#include "sqlite3ota.h" 20 +#include <tcl.h> 21 +#include <assert.h> 22 + 23 +/* From main.c (apparently...) */ 24 +extern const char *sqlite3ErrName(int); 25 + 26 +void test_ota_delta(sqlite3_context *pCtx, int nArg, sqlite3_value **apVal){ 27 + Tcl_Interp *interp = (Tcl_Interp*)sqlite3_user_data(pCtx); 28 + Tcl_Obj *pScript; 29 + int i; 30 + 31 + pScript = Tcl_NewObj(); 32 + Tcl_IncrRefCount(pScript); 33 + Tcl_ListObjAppendElement(0, pScript, Tcl_NewStringObj("ota_delta", -1)); 34 + for(i=0; i<nArg; i++){ 35 + sqlite3_value *pIn = apVal[i]; 36 + const char *z = (const char*)sqlite3_value_text(pIn); 37 + Tcl_ListObjAppendElement(0, pScript, Tcl_NewStringObj(z, -1)); 38 + } 39 + 40 + if( TCL_OK==Tcl_EvalObjEx(interp, pScript, TCL_GLOBAL_ONLY) ){ 41 + const char *z = Tcl_GetStringResult(interp); 42 + sqlite3_result_text(pCtx, z, -1, SQLITE_TRANSIENT); 43 + }else{ 44 + Tcl_BackgroundError(interp); 45 + } 46 + 47 + Tcl_DecrRefCount(pScript); 48 +} 49 + 50 + 51 +static int test_sqlite3ota_cmd( 52 + ClientData clientData, 53 + Tcl_Interp *interp, 54 + int objc, 55 + Tcl_Obj *CONST objv[] 56 +){ 57 + int ret = TCL_OK; 58 + sqlite3ota *pOta = (sqlite3ota*)clientData; 59 + const char *azMethod[] = { "step", "close", "create_ota_delta", 0 }; 60 + int iMethod; 61 + 62 + if( objc!=2 ){ 63 + Tcl_WrongNumArgs(interp, 1, objv, "METHOD"); 64 + return TCL_ERROR; 65 + } 66 + if( Tcl_GetIndexFromObj(interp, objv[1], azMethod, "method", 0, &iMethod) ){ 67 + return TCL_ERROR; 68 + } 69 + 70 + switch( iMethod ){ 71 + case 0: /* step */ { 72 + int rc = sqlite3ota_step(pOta); 73 + Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1)); 74 + break; 75 + } 76 + 77 + case 1: /* close */ { 78 + char *zErrmsg = 0; 79 + int rc; 80 + Tcl_DeleteCommand(interp, Tcl_GetString(objv[0])); 81 + rc = sqlite3ota_close(pOta, &zErrmsg); 82 + if( rc==SQLITE_OK || rc==SQLITE_DONE ){ 83 + Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1)); 84 + assert( zErrmsg==0 ); 85 + }else{ 86 + Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1)); 87 + if( zErrmsg ){ 88 + Tcl_AppendResult(interp, " - ", zErrmsg, 0); 89 + sqlite3_free(zErrmsg); 90 + } 91 + ret = TCL_ERROR; 92 + } 93 + break; 94 + } 95 + 96 + case 2: /* create_ota_delta */ { 97 + sqlite3 *db = sqlite3ota_db(pOta, 0); 98 + int rc = sqlite3_create_function( 99 + db, "ota_delta", -1, SQLITE_UTF8, (void*)interp, test_ota_delta, 0, 0 100 + ); 101 + Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1)); 102 + ret = (rc==SQLITE_OK ? TCL_OK : TCL_ERROR); 103 + break; 104 + } 105 + 106 + default: /* seems unlikely */ 107 + assert( !"cannot happen" ); 108 + break; 109 + } 110 + 111 + return ret; 112 +} 113 + 114 +/* 115 +** Tclcmd: sqlite3ota CMD <target-db> <ota-db> ?<state-db>? 116 +*/ 117 +static int test_sqlite3ota( 118 + ClientData clientData, 119 + Tcl_Interp *interp, 120 + int objc, 121 + Tcl_Obj *CONST objv[] 122 +){ 123 + sqlite3ota *pOta = 0; 124 + const char *zCmd; 125 + const char *zTarget; 126 + const char *zOta; 127 + 128 + if( objc!=4 && objc!=5 ){ 129 + Tcl_WrongNumArgs(interp, 1, objv, "NAME TARGET-DB OTA-DB ?STATE-DB?"); 130 + return TCL_ERROR; 131 + } 132 + zCmd = Tcl_GetString(objv[1]); 133 + zTarget = Tcl_GetString(objv[2]); 134 + zOta = Tcl_GetString(objv[3]); 135 + 136 + if( objc==4 ){ 137 + pOta = sqlite3ota_open(zTarget, zOta); 138 + }else{ 139 + const char *zStateDb = Tcl_GetString(objv[4]); 140 + pOta = sqlite3ota_open_v2(zTarget, zOta, zStateDb); 141 + } 142 + Tcl_CreateObjCommand(interp, zCmd, test_sqlite3ota_cmd, (ClientData)pOta, 0); 143 + Tcl_SetObjResult(interp, objv[1]); 144 + return TCL_OK; 145 +} 146 + 147 +/* 148 +** Tclcmd: sqlite3ota_create_vfs ?-default? NAME PARENT 149 +*/ 150 +static int test_sqlite3ota_create_vfs( 151 + ClientData clientData, 152 + Tcl_Interp *interp, 153 + int objc, 154 + Tcl_Obj *CONST objv[] 155 +){ 156 + const char *zName; 157 + const char *zParent; 158 + int rc; 159 + 160 + if( objc!=3 && objc!=4 ){ 161 + Tcl_WrongNumArgs(interp, 1, objv, "?-default? NAME PARENT"); 162 + return TCL_ERROR; 163 + } 164 + 165 + zName = Tcl_GetString(objv[objc-2]); 166 + zParent = Tcl_GetString(objv[objc-1]); 167 + if( zParent[0]=='\0' ) zParent = 0; 168 + 169 + rc = sqlite3ota_create_vfs(zName, zParent); 170 + if( rc!=SQLITE_OK ){ 171 + Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1)); 172 + return TCL_ERROR; 173 + }else if( objc==4 ){ 174 + sqlite3_vfs *pVfs = sqlite3_vfs_find(zName); 175 + sqlite3_vfs_register(pVfs, 1); 176 + } 177 + 178 + Tcl_ResetResult(interp); 179 + return TCL_OK; 180 +} 181 + 182 +/* 183 +** Tclcmd: sqlite3ota_destroy_vfs NAME 184 +*/ 185 +static int test_sqlite3ota_destroy_vfs( 186 + ClientData clientData, 187 + Tcl_Interp *interp, 188 + int objc, 189 + Tcl_Obj *CONST objv[] 190 +){ 191 + const char *zName; 192 + 193 + if( objc!=2 ){ 194 + Tcl_WrongNumArgs(interp, 1, objv, "NAME"); 195 + return TCL_ERROR; 196 + } 197 + 198 + zName = Tcl_GetString(objv[1]); 199 + sqlite3ota_destroy_vfs(zName); 200 + return TCL_OK; 201 +} 202 + 203 +/* 204 +** Tclcmd: sqlite3ota_internal_test 205 +*/ 206 +static int test_sqlite3ota_internal_test( 207 + ClientData clientData, 208 + Tcl_Interp *interp, 209 + int objc, 210 + Tcl_Obj *CONST objv[] 211 +){ 212 + sqlite3 *db; 213 + 214 + if( objc!=1 ){ 215 + Tcl_WrongNumArgs(interp, 1, objv, ""); 216 + return TCL_ERROR; 217 + } 218 + 219 + db = sqlite3ota_db(0, 0); 220 + if( db!=0 ){ 221 + Tcl_AppendResult(interp, "sqlite3ota_db(0, 0)!=0", 0); 222 + return TCL_ERROR; 223 + } 224 + 225 + return TCL_OK; 226 +} 227 + 228 +int SqliteOta_Init(Tcl_Interp *interp){ 229 + static struct { 230 + char *zName; 231 + Tcl_ObjCmdProc *xProc; 232 + } aObjCmd[] = { 233 + { "sqlite3ota", test_sqlite3ota }, 234 + { "sqlite3ota_create_vfs", test_sqlite3ota_create_vfs }, 235 + { "sqlite3ota_destroy_vfs", test_sqlite3ota_destroy_vfs }, 236 + { "sqlite3ota_internal_test", test_sqlite3ota_internal_test }, 237 + }; 238 + int i; 239 + for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){ 240 + Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, 0, 0); 241 + } 242 + return TCL_OK; 243 +} 244 + 245 +#else 246 +#include <tcl.h> 247 +int SqliteOta_Init(Tcl_Interp *interp){ return TCL_OK; } 248 +#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_OTA) */ 249 +#endif /* defined(SQLITE_TEST) */ 250 +
Changes to main.mk.
61 61 fts3_write.o func.o global.o hash.o \ 62 62 icu.o insert.o journal.o legacy.o loadext.o \ 63 63 main.o malloc.o mem0.o mem1.o mem2.o mem3.o mem5.o \ 64 64 memjournal.o \ 65 65 mutex.o mutex_noop.o mutex_unix.o mutex_w32.o \ 66 66 notify.o opcodes.o os.o os_unix.o os_win.o \ 67 67 pager.o pcache.o pcache1.o pragma.o prepare.o printf.o \ 68 - random.o resolve.o rowset.o rtree.o select.o status.o \ 68 + random.o resolve.o rowset.o rtree.o select.o sqlite3ota.o status.o \ 69 69 table.o threads.o tokenize.o trigger.o \ 70 70 update.o userauth.o util.o vacuum.o \ 71 71 vdbeapi.o vdbeaux.o vdbeblob.o vdbemem.o vdbesort.o \ 72 72 vdbetrace.o wal.o walker.o where.o utf.o vtab.o 73 73 74 74 75 75 ................................................................................ 217 217 SRC += \ 218 218 $(TOP)/ext/rtree/sqlite3rtree.h \ 219 219 $(TOP)/ext/rtree/rtree.h \ 220 220 $(TOP)/ext/rtree/rtree.c 221 221 SRC += \ 222 222 $(TOP)/ext/userauth/userauth.c \ 223 223 $(TOP)/ext/userauth/sqlite3userauth.h 224 +SRC += \ 225 + $(TOP)/ext/ota/sqlite3ota.c \ 226 + $(TOP)/ext/ota/sqlite3ota.h 224 227 225 228 # Generated source code files 226 229 # 227 230 SRC += \ 228 231 keywordhash.h \ 229 232 opcodes.c \ 230 233 opcodes.h \ ................................................................................ 234 237 235 238 236 239 # Source code to the test files. 237 240 # 238 241 TESTSRC = \ 239 242 $(TOP)/ext/fts3/fts3_term.c \ 240 243 $(TOP)/ext/fts3/fts3_test.c \ 244 + $(TOP)/ext/ota/test_ota.c \ 241 245 $(TOP)/src/test1.c \ 242 246 $(TOP)/src/test2.c \ 243 247 $(TOP)/src/test3.c \ 244 248 $(TOP)/src/test4.c \ 245 249 $(TOP)/src/test5.c \ 246 250 $(TOP)/src/test6.c \ 247 251 $(TOP)/src/test7.c \ ................................................................................ 335 339 $(TOP)/src/where.c \ 336 340 parse.c \ 337 341 $(TOP)/ext/fts3/fts3.c \ 338 342 $(TOP)/ext/fts3/fts3_aux.c \ 339 343 $(TOP)/ext/fts3/fts3_expr.c \ 340 344 $(TOP)/ext/fts3/fts3_tokenizer.c \ 341 345 $(TOP)/ext/fts3/fts3_write.c \ 342 - $(TOP)/ext/async/sqlite3async.c 346 + $(TOP)/ext/async/sqlite3async.c 343 347 344 348 # Header files used by all library source files. 345 349 # 346 350 HDR = \ 347 351 $(TOP)/src/btree.h \ 348 352 $(TOP)/src/btreeInt.h \ 349 353 $(TOP)/src/hash.h \ ................................................................................ 599 603 600 604 rtree.o: $(TOP)/ext/rtree/rtree.c $(HDR) $(EXTHDR) 601 605 $(TCCX) -DSQLITE_CORE -c $(TOP)/ext/rtree/rtree.c 602 606 603 607 userauth.o: $(TOP)/ext/userauth/userauth.c $(HDR) $(EXTHDR) 604 608 $(TCCX) -DSQLITE_CORE -c $(TOP)/ext/userauth/userauth.c 605 609 610 +sqlite3ota.o: $(TOP)/ext/ota/sqlite3ota.c $(HDR) $(EXTHDR) 611 + $(TCCX) -DSQLITE_CORE -c $(TOP)/ext/ota/sqlite3ota.c 612 + 606 613 607 614 # Rules for building test programs and for running tests 608 615 # 609 616 tclsqlite3: $(TOP)/src/tclsqlite.c libsqlite3.a 610 617 $(TCCX) $(TCL_FLAGS) -DTCLSH=1 -o tclsqlite3 \ 611 618 $(TOP)/src/tclsqlite.c libsqlite3.a $(LIBTCL) $(THREADLIB) 612 619 ................................................................................ 730 737 $(TCC) -o LogEst$(EXE) $(TOP)/tool/logest.c 731 738 732 739 wordcount$(EXE): $(TOP)/test/wordcount.c sqlite3.c 733 740 $(TCC) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -o wordcount$(EXE) \ 734 741 $(TOP)/test/wordcount.c sqlite3.c 735 742 736 743 speedtest1$(EXE): $(TOP)/test/speedtest1.c sqlite3.o 737 - $(TCC) -I. -o speedtest1$(EXE) $(TOP)/test/speedtest1.c sqlite3.o $(THREADLIB) 744 + $(TCC) -I. $(OTAFLAGS) -o speedtest1$(EXE) $(TOP)/test/speedtest1.c sqlite3.o $(THREADLIB) 745 + 746 +ota$(EXE): $(TOP)/ext/ota/ota.c $(TOP)/ext/ota/sqlite3ota.c sqlite3.o 747 + $(TCC) -I. -o ota$(EXE) $(TOP)/ext/ota/ota.c sqlite3.o \ 748 + $(THREADLIB) 738 749 739 750 # This target will fail if the SQLite amalgamation contains any exported 740 751 # symbols that do not begin with "sqlite3_". It is run as part of the 741 752 # releasetest.tcl script. 742 753 # 743 754 checksymbols: sqlite3.o 744 755 nm -g --defined-only sqlite3.o | grep -v " sqlite3_" ; test $$? -ne 0
Changes to src/sqlite.h.in.
952 952 ** 953 953 ** <li>[[SQLITE_FCNTL_WIN32_SET_HANDLE]] 954 954 ** The [SQLITE_FCNTL_WIN32_SET_HANDLE] opcode is used for debugging. This 955 955 ** opcode causes the xFileControl method to swap the file handle with the one 956 956 ** pointed to by the pArg argument. This capability is used during testing 957 957 ** and only needs to be supported when SQLITE_TEST is defined. 958 958 ** 959 -** <li>[[SQLITE_FCNTL_WAL_BLOCK]] 959 +* <li>[[SQLITE_FCNTL_WAL_BLOCK]] 960 960 ** The [SQLITE_FCNTL_WAL_BLOCK] is a signal to the VFS layer that it might 961 961 ** be advantageous to block on the next WAL lock if the lock is not immediately 962 962 ** available. The WAL subsystem issues this signal during rare 963 963 ** circumstances in order to fix a problem with priority inversion. 964 964 ** Applications should <em>not</em> use this file-control. 965 965 ** 966 +** <li>[[SQLITE_FCNTL_ZIPVFS]] 967 +** The [SQLITE_FCNTL_ZIPVFS] opcode is implemented by zipvfs only. All other 968 +** VFS should return SQLITE_NOTFOUND for this opcode. 969 +** 970 +** <li>[[SQLITE_FCNTL_OTA]] 971 +** The [SQLITE_FCNTL_OTA] opcode is implemented by the special VFS used by 972 +** the OTA extension only. All other VFS should return SQLITE_NOTFOUND for 973 +** this opcode. 966 974 ** </ul> 967 975 */ 968 976 #define SQLITE_FCNTL_LOCKSTATE 1 969 977 #define SQLITE_FCNTL_GET_LOCKPROXYFILE 2 970 978 #define SQLITE_FCNTL_SET_LOCKPROXYFILE 3 971 979 #define SQLITE_FCNTL_LAST_ERRNO 4 972 980 #define SQLITE_FCNTL_SIZE_HINT 5 ................................................................................ 984 992 #define SQLITE_FCNTL_MMAP_SIZE 18 985 993 #define SQLITE_FCNTL_TRACE 19 986 994 #define SQLITE_FCNTL_HAS_MOVED 20 987 995 #define SQLITE_FCNTL_SYNC 21 988 996 #define SQLITE_FCNTL_COMMIT_PHASETWO 22 989 997 #define SQLITE_FCNTL_WIN32_SET_HANDLE 23 990 998 #define SQLITE_FCNTL_WAL_BLOCK 24 999 +#define SQLITE_FCNTL_ZIPVFS 25 1000 +#define SQLITE_FCNTL_OTA 26 991 1001 992 1002 /* deprecated names */ 993 1003 #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE 994 1004 #define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE 995 1005 #define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO 996 1006 997 1007
Changes to src/tclsqlite.c.
3756 3756 extern int Sqlitetestintarray_Init(Tcl_Interp*); 3757 3757 extern int Sqlitetestvfs_Init(Tcl_Interp *); 3758 3758 extern int Sqlitetestrtree_Init(Tcl_Interp*); 3759 3759 extern int Sqlitequota_Init(Tcl_Interp*); 3760 3760 extern int Sqlitemultiplex_Init(Tcl_Interp*); 3761 3761 extern int SqliteSuperlock_Init(Tcl_Interp*); 3762 3762 extern int SqlitetestSyscall_Init(Tcl_Interp*); 3763 + extern int SqliteOta_Init(Tcl_Interp*); 3763 3764 3764 3765 #if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4) 3765 3766 extern int Sqlitetestfts3_Init(Tcl_Interp *interp); 3766 3767 #endif 3767 3768 3768 3769 #ifdef SQLITE_ENABLE_ZIPVFS 3769 3770 extern int Zipvfs_Init(Tcl_Interp*); ................................................................................ 3799 3800 Sqlitetestintarray_Init(interp); 3800 3801 Sqlitetestvfs_Init(interp); 3801 3802 Sqlitetestrtree_Init(interp); 3802 3803 Sqlitequota_Init(interp); 3803 3804 Sqlitemultiplex_Init(interp); 3804 3805 SqliteSuperlock_Init(interp); 3805 3806 SqlitetestSyscall_Init(interp); 3807 + SqliteOta_Init(interp); 3806 3808 3807 3809 #if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4) 3808 3810 Sqlitetestfts3_Init(interp); 3809 3811 #endif 3810 3812 3811 3813 Tcl_CreateObjCommand( 3812 3814 interp, "load_testfixture_extensions", init_all_cmd, 0, 0
Changes to src/test_config.c.
425 425 Tcl_SetVar2(interp, "sqlite_options", "mergesort", "1", TCL_GLOBAL_ONLY); 426 426 427 427 #ifdef SQLITE_OMIT_OR_OPTIMIZATION 428 428 Tcl_SetVar2(interp, "sqlite_options", "or_opt", "0", TCL_GLOBAL_ONLY); 429 429 #else 430 430 Tcl_SetVar2(interp, "sqlite_options", "or_opt", "1", TCL_GLOBAL_ONLY); 431 431 #endif 432 + 433 +#ifdef SQLITE_ENABLE_OTA 434 + Tcl_SetVar2(interp, "sqlite_options", "ota", "1", TCL_GLOBAL_ONLY); 435 +#else 436 + Tcl_SetVar2(interp, "sqlite_options", "ota", "0", TCL_GLOBAL_ONLY); 437 +#endif 432 438 433 439 #ifdef SQLITE_OMIT_PAGER_PRAGMAS 434 440 Tcl_SetVar2(interp, "sqlite_options", "pager_pragmas", "0", TCL_GLOBAL_ONLY); 435 441 #else 436 442 Tcl_SetVar2(interp, "sqlite_options", "pager_pragmas", "1", TCL_GLOBAL_ONLY); 437 443 #endif 438 444
Added test/ota.test.
1 +# 2014 September 20 2 +# 3 +# May you do good and not evil. 4 +# May you find forgiveness for yourself and forgive others. 5 +# May you share freely, never taking more than you give. 6 +# 7 +#*********************************************************************** 8 +# This file runs all rtree related tests. 9 +# 10 + 11 +set testdir [file dirname $argv0] 12 +source $testdir/permutations.test 13 + 14 +ifcapable !ota { finish_test ; return } 15 + 16 +run_test_suite ota 17 +finish_test 18 +
Changes to test/permutations.test.
109 109 speed1.test speed1p.test speed2.test speed3.test speed4.test 110 110 speed4p.test sqllimits1.test tkt2686.test thread001.test thread002.test 111 111 thread003.test thread004.test thread005.test trans2.test vacuum3.test 112 112 incrvacuum_ioerr.test autovacuum_crash.test btree8.test shared_err.test 113 113 vtab_err.test walslow.test walcrash.test walcrash3.test 114 114 walthread.test rtree3.test indexfault.test securedel2.test 115 115 sort3.test sort4.test fts4growth.test fts4growth2.test 116 - bigsort.test 116 + bigsort.test ota.test 117 117 }] 118 118 if {[info exists ::env(QUICKTEST_INCLUDE)]} { 119 119 set allquicktests [concat $allquicktests $::env(QUICKTEST_INCLUDE)] 120 120 } 121 121 if {[info exists ::env(QUICKTEST_OMIT)]} { 122 122 foreach x [split $::env(QUICKTEST_OMIT) ,] { 123 123 regsub -all \\y$x\\y $allquicktests {} allquicktests ................................................................................ 934 934 fts3am.test fts3an.test fts3ao.test fts3b.test 935 935 fts3c.test fts3d.test fts3e.test fts3query.test 936 936 } 937 937 938 938 test_suite "rtree" -description { 939 939 All R-tree related tests. Provides coverage of source file rtree.c. 940 940 } -files [glob -nocomplain $::testdir/../ext/rtree/*.test] 941 + 942 +test_suite "ota" -description { 943 + OTA tests. 944 +} -files [ 945 + test_set [glob -nocomplain $::testdir/../ext/ota/*.test] -exclude ota.test 946 +] 941 947 942 948 test_suite "no_optimization" -description { 943 949 Run test scripts with optimizations disabled using the 944 950 sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS) interface. 945 951 } -files { 946 952 where.test where2.test where3.test where4.test where5.test 947 953 where6.test where7.test where8.test where9.test
Changes to test/releasetest.tcl.
112 112 -DSQLITE_MAX_ATTACHED=125 113 113 } 114 114 "Fast-One" { 115 115 -O6 116 116 -DSQLITE_ENABLE_FTS4=1 117 117 -DSQLITE_ENABLE_RTREE=1 118 118 -DSQLITE_ENABLE_STAT4 119 + -DSQLITE_ENABLE_OTA 119 120 -DSQLITE_MAX_ATTACHED=125 120 121 } 121 122 "Device-One" { 122 123 -O2 123 124 -DSQLITE_DEBUG=1 124 125 -DSQLITE_DEFAULT_AUTOVACUUM=1 125 126 -DSQLITE_DEFAULT_CACHE_SIZE=64
Changes to test/speedtest1.c.
38 38 #include "sqlite3.h" 39 39 #include <assert.h> 40 40 #include <stdio.h> 41 41 #include <stdlib.h> 42 42 #include <stdarg.h> 43 43 #include <string.h> 44 44 #include <ctype.h> 45 + 46 +#ifdef SQLITE_ENABLE_OTA 47 +# include "sqlite3ota.h" 48 +#endif 45 49 46 50 /* All global state is held in this structure */ 47 51 static struct Global { 48 52 sqlite3 *db; /* The open database connection */ 49 53 sqlite3_stmt *pStmt; /* Current SQL statement */ 50 54 sqlite3_int64 iStart; /* Start-time for the current test */ 51 55 sqlite3_int64 iTotal; /* Total time */ ................................................................................ 530 534 zNum[len+1] = 0; 531 535 sqlite3_bind_text(g.pStmt, 1, zNum, len, SQLITE_STATIC); 532 536 speedtest1_run(); 533 537 } 534 538 speedtest1_exec("COMMIT"); 535 539 speedtest1_end_test(); 536 540 537 - n = 10; //g.szTest/5; 541 + n = 10; /* g.szTest/5; */ 538 542 speedtest1_begin_test(145, "%d SELECTS w/ORDER BY and LIMIT, unindexed", n); 539 543 speedtest1_exec("BEGIN"); 540 544 speedtest1_prepare( 541 545 "SELECT a, b, c FROM t1 WHERE c LIKE ?1\n" 542 546 " ORDER BY a LIMIT 10; -- %d times", n 543 547 ); 544 548 for(i=1; i<=n; i++){ ................................................................................ 1200 1204 nLook = integerValue(argv[i+1]); 1201 1205 szLook = integerValue(argv[i+2]); 1202 1206 i += 2; 1203 1207 }else if( strcmp(z,"nosync")==0 ){ 1204 1208 noSync = 1; 1205 1209 }else if( strcmp(z,"notnull")==0 ){ 1206 1210 g.zNN = "NOT NULL"; 1211 +#ifdef SQLITE_ENABLE_OTA 1212 + }else if( strcmp(z,"ota")==0 ){ 1213 + sqlite3ota_create_vfs("ota", 0); 1214 + sqlite3_vfs_register(sqlite3_vfs_find("ota"), 1); 1215 +#endif 1207 1216 }else if( strcmp(z,"pagesize")==0 ){ 1208 1217 if( i>=argc-1 ) fatal_error("missing argument on %s\n", argv[i]); 1209 1218 pageSize = integerValue(argv[++i]); 1210 1219 }else if( strcmp(z,"pcache")==0 ){ 1211 1220 if( i>=argc-2 ) fatal_error("missing arguments on %s\n", argv[i]); 1212 1221 nPCache = integerValue(argv[i+1]); 1213 1222 szPCache = integerValue(argv[i+2]);
Changes to test/tester.tcl.
1338 1338 # default, so here we force it to the "nativename" format. 1339 1339 set cfile [string map {\\ \\\\} [file nativename [file join [get_pwd] $crashfile]]] 1340 1340 1341 1341 set f [open crash.tcl w] 1342 1342 puts $f "sqlite3_crash_enable 1" 1343 1343 puts $f "sqlite3_crashparams $blocksize $dc $crashdelay $cfile" 1344 1344 puts $f "sqlite3_test_control_pending_byte $::sqlite_pending_byte" 1345 - puts $f $opendb 1346 1345 1347 1346 # This block sets the cache size of the main database to 10 1348 1347 # pages. This is done in case the build is configured to omit 1349 1348 # "PRAGMA cache_size". 1350 - puts $f {db eval {SELECT * FROM sqlite_master;}} 1351 - puts $f {set bt [btree_from_db db]} 1352 - puts $f {btree_set_cache_size $bt 10} 1349 + if {$opendb!=""} { 1350 + puts $f $opendb 1351 + puts $f {db eval {SELECT * FROM sqlite_master;}} 1352 + puts $f {set bt [btree_from_db db]} 1353 + puts $f {btree_set_cache_size $bt 10} 1354 + } 1353 1355 1354 1356 if {$prngseed} { 1355 1357 set seed [expr {$prngseed%10007+1}] 1356 1358 # puts seed=$seed 1357 1359 puts $f "db eval {SELECT randomblob($seed)}" 1358 1360 } 1359 1361
Changes to tool/mksqlite3c.tcl.
107 107 os_win.h 108 108 os.h 109 109 pager.h 110 110 parse.h 111 111 pcache.h 112 112 pragma.h 113 113 rtree.h 114 - sqlite3ext.h 115 114 sqlite3.h 115 + sqlite3ext.h 116 + sqlite3ota.h 116 117 sqliteicu.h 117 118 sqliteInt.h 118 119 sqliteLimit.h 119 120 vdbe.h 120 121 vdbeInt.h 121 122 vxworks.h 122 123 wal.h ................................................................................ 210 211 # Skip adding the SQLITE_PRIVATE or SQLITE_API keyword before 211 212 # functions if this header file does not need it. 212 213 if {![info exists varonly_hdr($tail)] 213 214 && [regexp $declpattern $line all rettype funcname rest]} { 214 215 regsub {^SQLITE_API } $line {} line 215 216 # Add the SQLITE_PRIVATE or SQLITE_API keyword before functions. 216 217 # so that linkage can be modified at compile-time. 217 - if {[regexp {^sqlite3_} $funcname]} { 218 + if {[regexp {^sqlite3(_|ota_)} $funcname]} { 218 219 set line SQLITE_API 219 220 append line " " [string trim $rettype] 220 221 if {[string index $rettype end] ne "*"} { 221 222 append line " " 222 223 } 223 224 if {[lsearch -exact $cdecllist $funcname] >= 0} { 224 225 append line SQLITE_CDECL ................................................................................ 364 365 fts3_snippet.c 365 366 fts3_unicode.c 366 367 fts3_unicode2.c 367 368 368 369 rtree.c 369 370 icu.c 370 371 fts3_icu.c 372 + sqlite3ota.c 371 373 dbstat.c 372 374 } { 373 375 copy_file tsrc/$file 374 376 } 375 377 376 378 close $out