1# 2009 January 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# This file implements regression tests for SQLite library. The 12# focus of this file is testing the sqlite3_backup_XXX API. 13# 14# $Id: backup.test,v 1.11 2009/06/05 17:09:12 drh Exp $ 15 16set testdir [file dirname $argv0] 17source $testdir/tester.tcl 18 19do_not_use_codec 20 21#--------------------------------------------------------------------- 22# Test organization: 23# 24# backup-1.*: Warm-body tests. 25# 26# backup-2.*: Test backup under various conditions. To and from in-memory 27# databases. To and from empty/populated databases. etc. 28# 29# backup-3.*: Verify that the locking-page (pending byte page) is handled. 30# 31# backup-4.*: Test various error conditions. 32# 33# backup-5.*: Test the source database being modified during a backup. 34# 35# backup-6.*: Test the backup_remaining() and backup_pagecount() APIs. 36# 37# backup-7.*: Test SQLITE_BUSY and SQLITE_LOCKED errors. 38# 39# backup-8.*: Test multiple simultaneous backup operations. 40# 41# backup-9.*: Test that passing a negative argument to backup_step() is 42# interpreted as "copy the whole file". 43# 44# backup-10.*: Test writing the source database mid backup. 45# 46 47proc data_checksum {db file} { $db one "SELECT md5sum(a, b) FROM ${file}.t1" } 48proc test_contents {name db1 file1 db2 file2} { 49 $db2 eval {select * from sqlite_master} 50 $db1 eval {select * from sqlite_master} 51 set checksum [data_checksum $db2 $file2] 52 uplevel [list do_test $name [list data_checksum $db1 $file1] $checksum] 53} 54 55do_test backup-1.1 { 56 execsql { 57 BEGIN; 58 CREATE TABLE t1(a, b); 59 CREATE INDEX i1 ON t1(a, b); 60 INSERT INTO t1 VALUES(1, randstr(1000,1000)); 61 INSERT INTO t1 VALUES(2, randstr(1000,1000)); 62 INSERT INTO t1 VALUES(3, randstr(1000,1000)); 63 INSERT INTO t1 VALUES(4, randstr(1000,1000)); 64 INSERT INTO t1 VALUES(5, randstr(1000,1000)); 65 COMMIT; 66 } 67} {} 68 69# Sanity check to verify that the [test_contents] proc works. 70# 71test_contents backup-1.2 db main db main 72 73# Check that it is possible to create and finish backup operations. 74# 75do_test backup-1.3.1 { 76 file delete test2.db 77 sqlite3 db2 test2.db 78 sqlite3_backup B db2 main db main 79} {B} 80do_test backup-1.3.2 { 81 B finish 82} {SQLITE_OK} 83do_test backup-1.3.3 { 84 info commands B 85} {} 86 87# Simplest backup operation. Backup test.db to test2.db. test2.db is 88# initially empty. test.db uses the default page size. 89# 90do_test backup-1.4.1 { 91 sqlite3_backup B db2 main db main 92} {B} 93do_test backup-1.4.2 { 94 B step 200 95} {SQLITE_DONE} 96do_test backup-1.4.3 { 97 B finish 98} {SQLITE_OK} 99do_test backup-1.4.4 { 100 info commands B 101} {} 102test_contents backup-1.4.5 db2 main db main 103db close 104db2 close 105# 106# End of backup-1.* tests. 107#--------------------------------------------------------------------- 108 109 110#--------------------------------------------------------------------- 111# The following tests, backup-2.*, are based on the following procedure: 112# 113# 1) Populate the source database. 114# 2) Populate the destination database. 115# 3) Run the backup to completion. (backup-2.*.1) 116# 4) Integrity check the destination db. (backup-2.*.2) 117# 5) Check that the contents of the destination db is the same as that 118# of the source db. (backup-2.*.3) 119# 120# The test is run with all possible combinations of the following 121# input parameters, except that if the destination is an in-memory 122# database, the only page size tested is 1024 bytes (the same as the 123# source page-size). 124# 125# * Source database is an in-memory database, OR 126# * Source database is a file-backed database. 127# 128# * Target database is an in-memory database, OR 129# * Target database is a file-backed database. 130# 131# * Destination database is a main file, OR 132# * Destination database is an attached file, OR 133# * Destination database is a temp database. 134# 135# * Target database is empty (zero bytes), OR 136# * Target database is larger than the source, OR 137# * Target database is smaller than the source. 138# 139# * Target database page-size is the same as the source, OR 140# * Target database page-size is larger than the source, OR 141# * Target database page-size is smaller than the source. 142# 143# * Each call to step copies a single page, OR 144# * A single call to step copies the entire source database. 145# 146set iTest 1 147foreach zSrcFile {test.db :memory:} { 148foreach zDestFile {test2.db :memory:} { 149foreach zOpenScript [list { 150 sqlite3 db $zSrcFile 151 sqlite3 db2 $zSrcFile 152 db2 eval "ATTACH '$zDestFile' AS bak" 153 set db_dest db2 154 set file_dest bak 155} { 156 sqlite3 db $zSrcFile 157 sqlite3 db2 $zDestFile 158 set db_dest db2 159 set file_dest main 160} { 161 sqlite3 db $zSrcFile 162 sqlite3 db2 $zDestFile 163 set db_dest db2 164 set file_dest temp 165}] { 166foreach rows_dest {0 3 10} { 167foreach pgsz_dest {1024} { 168foreach nPagePerStep {1 200} { 169 170 # Open the databases. 171 catch { file delete -force -- test.db } 172 catch { file delete -force -- test2.db } 173 eval $zOpenScript 174 175 # Set to true if copying to an in-memory destination. Copying to an 176 # in-memory destination is only possible if the initial destination 177 # page size is the same as the source page size (in this case 1024 bytes). 178 # 179 set isMemDest [expr { 180 $zDestFile eq ":memory:" || $file_dest eq "temp" && $TEMP_STORE>=2 181 }] 182 183 if { $isMemDest==0 || $pgsz_dest == 1024 } { 184 if 0 { 185 puts -nonewline "Test $iTest: src=$zSrcFile dest=$zDestFile" 186 puts -nonewline " (as $db_dest.$file_dest)" 187 puts -nonewline " rows_dest=$rows_dest pgsz_dest=$pgsz_dest" 188 puts "" 189 } 190 191 # Set up the content of the source database. 192 execsql { 193 PRAGMA page_size = 1024; 194 PRAGMA cache_size = 4000; 195 BEGIN; 196 CREATE TABLE t1(a, b); 197 CREATE INDEX i1 ON t1(a, b); 198 INSERT INTO t1 VALUES(1, randstr(1000,1000)); 199 INSERT INTO t1 VALUES(2, randstr(1000,1000)); 200 INSERT INTO t1 VALUES(3, randstr(1000,1000)); 201 INSERT INTO t1 VALUES(4, randstr(1000,1000)); 202 INSERT INTO t1 VALUES(5, randstr(1000,1000)); 203 COMMIT; 204 } 205 206 207 208 # Set up the content of the target database. 209 execsql "PRAGMA ${file_dest}.page_size = ${pgsz_dest}" $db_dest 210 execsql "PRAGMA ${file_dest}.cache_size = 4000" $db_dest 211 if {$rows_dest != 0} { 212 execsql " 213 CREATE TABLE ${file_dest}.t1(a, b); 214 CREATE INDEX ${file_dest}.i1 ON t1(a, b); 215 " $db_dest 216 for {set ii 0} {$ii < $rows_dest} {incr ii} { 217 execsql " 218 INSERT INTO ${file_dest}.t1 VALUES(1, randstr(1000,1000)) 219 " $db_dest 220 } 221 } 222 223 # Backup the source database. 224 do_test backup-2.$iTest.1 { 225 sqlite3_backup B $db_dest $file_dest db main 226 while {[B step $nPagePerStep]=="SQLITE_OK"} {} 227 B finish 228 } {SQLITE_OK} 229 230 # Run integrity check on the backup. 231 do_test backup-2.$iTest.2 { 232 execsql "PRAGMA ${file_dest}.integrity_check" $db_dest 233 } {ok} 234 235 test_contents backup-2.$iTest.3 db main $db_dest $file_dest 236 237 } 238 239 db close 240 catch {db2 close} 241 incr iTest 242 243} } } } } } 244# 245# End of backup-2.* tests. 246#--------------------------------------------------------------------- 247 248 249#--------------------------------------------------------------------- 250# The following tests, backup-4.*, test various error conditions: 251# 252# backup-4.1.*: Test invalid database names. 253# 254# backup-4.2.*: Test that the source database cannot be detached while 255# a backup is in progress. 256# 257# backup-4.3.*: Test that the source database handle cannot be closed 258# while a backup is in progress. 259# 260# backup-4.4.*: Test an attempt to specify the same handle for the 261# source and destination databases. 262# 263# backup-4.5.*: Test that an in-memory destination with a different 264# page-size to the source database is an error. 265# 266sqlite3 db test.db 267sqlite3 db2 test2.db 268 269do_test backup-4.1.1 { 270 catch { sqlite3_backup B db aux db2 main } 271} {1} 272do_test backup-4.1.2 { 273 sqlite3_errmsg db 274} {unknown database aux} 275do_test backup-4.1.3 { 276 catch { sqlite3_backup B db main db2 aux } 277} {1} 278do_test backup-4.1.4 { 279 sqlite3_errmsg db 280} {unknown database aux} 281 282do_test backup-4.2.1 { 283 catch { file delete -force test3.db } 284 catch { file delete -force test4.db } 285 execsql { 286 ATTACH 'test3.db' AS aux1; 287 CREATE TABLE aux1.t1(a, b); 288 } 289 execsql { 290 ATTACH 'test4.db' AS aux2; 291 CREATE TABLE aux2.t2(a, b); 292 } db2 293 sqlite3_backup B db aux1 db2 aux2 294} {B} 295do_test backup-4.2.2 { 296 catchsql { DETACH aux2 } db2 297} {1 {database aux2 is locked}} 298do_test backup-4.2.3 { 299 B step 50 300} {SQLITE_DONE} 301do_test backup-4.2.4 { 302 B finish 303} {SQLITE_OK} 304 305do_test backup-4.3.1 { 306 sqlite3_backup B db aux1 db2 aux2 307} {B} 308do_test backup-4.3.2 { 309 db2 cache flush 310 sqlite3_close db2 311} {SQLITE_BUSY} 312do_test backup-4.3.3 { 313 sqlite3_errmsg db2 314} {unable to close due to unfinished backup operation} 315do_test backup-4.3.4 { 316 B step 50 317} {SQLITE_DONE} 318do_test backup-4.3.5 { 319 B finish 320} {SQLITE_OK} 321 322do_test backup-4.4.1 { 323 set rc [catch {sqlite3_backup B db main db aux1}] 324 list $rc [sqlite3_errcode db] [sqlite3_errmsg db] 325} {1 SQLITE_ERROR {source and destination must be distinct}} 326db close 327db2 close 328 329do_test backup-4.5.1 { 330 catch { file delete -force -- test.db } 331 sqlite3 db test.db 332 sqlite3 db2 :memory: 333 execsql { 334 CREATE TABLE t1(a, b); 335 INSERT INTO t1 VALUES(1, 2); 336 } 337 execsql { 338 PRAGMA page_size = 4096; 339 CREATE TABLE t2(a, b); 340 INSERT INTO t2 VALUES(3, 4); 341 } db2 342 sqlite3_backup B db2 main db main 343} {B} 344do_test backup-4.5.2 { 345 B step 5000 346} {SQLITE_READONLY} 347do_test backup-4.5.3 { 348 B finish 349} {SQLITE_READONLY} 350 351db close 352db2 close 353# 354# End of backup-5.* tests. 355#--------------------------------------------------------------------- 356 357#--------------------------------------------------------------------- 358# The following tests, backup-5.*, test that the backup works properly 359# when the source database is modified during the backup. Test cases 360# are organized as follows: 361# 362# backup-5.x.1.*: Nothing special. Modify the database mid-backup. 363# 364# backup-5.x.2.*: Modify the database mid-backup so that one or more 365# pages are written out due to cache stress. Then 366# rollback the transaction. 367# 368# backup-5.x.3.*: Database is vacuumed. 369# 370# backup-5.x.4.*: Database is vacuumed and the page-size modified. 371# 372# backup-5.x.5.*: Database is shrunk via incr-vacuum. 373# 374# Each test is run three times, in the following configurations: 375# 376# 1) Backing up file-to-file. The writer writes via an external pager. 377# 2) Backing up file-to-file. The writer writes via the same pager as 378# is used by the backup operation. 379# 3) Backing up memory-to-file. 380# 381set iTest 0 382file delete -force bak.db-wal 383foreach {writer file} {db test.db db :memory:} { 384 incr iTest 385 catch { file delete -force bak.db } 386 sqlite3 db2 bak.db 387 catch { file delete -force $file } 388 sqlite3 db $file 389 sqlite3 db3 $file 390 391 do_test backup-5.$iTest.1.1 { 392 execsql { 393 BEGIN; 394 CREATE TABLE t1(a, b); 395 CREATE INDEX i1 ON t1(a, b); 396 INSERT INTO t1 VALUES(1, randstr(1000,1000)); 397 INSERT INTO t1 VALUES(2, randstr(1000,1000)); 398 INSERT INTO t1 VALUES(3, randstr(1000,1000)); 399 INSERT INTO t1 VALUES(4, randstr(1000,1000)); 400 INSERT INTO t1 VALUES(5, randstr(1000,1000)); 401 COMMIT; 402 } 403 expr {[execsql {PRAGMA page_count}] > 10} 404 } {1} 405 do_test backup-5.$iTest.1.2 { 406 sqlite3_backup B db2 main db main 407 B step 5 408 } {SQLITE_OK} 409 do_test backup-5.$iTest.1.3 { 410 execsql { UPDATE t1 SET a = a + 1 } $writer 411 B step 500 412 } {SQLITE_DONE} 413 do_test backup-5.$iTest.1.4 { 414 B finish 415 } {SQLITE_OK} 416 integrity_check backup-5.$iTest.1.5 db2 417 test_contents backup-5.$iTest.1.6 db main db2 main 418 419 do_test backup-5.$iTest.2.1 { 420 execsql { 421 PRAGMA cache_size = 10; 422 BEGIN; 423 INSERT INTO t1 SELECT '', randstr(1000,1000) FROM t1; 424 INSERT INTO t1 SELECT '', randstr(1000,1000) FROM t1; 425 INSERT INTO t1 SELECT '', randstr(1000,1000) FROM t1; 426 INSERT INTO t1 SELECT '', randstr(1000,1000) FROM t1; 427 COMMIT; 428 } 429 } {} 430 do_test backup-5.$iTest.2.2 { 431 sqlite3_backup B db2 main db main 432 B step 50 433 } {SQLITE_OK} 434 do_test backup-5.$iTest.2.3 { 435 execsql { 436 BEGIN; 437 UPDATE t1 SET a = a + 1; 438 ROLLBACK; 439 } $writer 440 B step 5000 441 } {SQLITE_DONE} 442 do_test backup-5.$iTest.2.4 { 443 B finish 444 } {SQLITE_OK} 445 integrity_check backup-5.$iTest.2.5 db2 446 test_contents backup-5.$iTest.2.6 db main db2 main 447 448 do_test backup-5.$iTest.3.1 { 449 execsql { UPDATE t1 SET b = randstr(1000,1000) } 450 } {} 451 do_test backup-5.$iTest.3.2 { 452 sqlite3_backup B db2 main db main 453 B step 50 454 } {SQLITE_OK} 455 do_test backup-5.$iTest.3.3 { 456 execsql { VACUUM } $writer 457 B step 5000 458 } {SQLITE_DONE} 459 do_test backup-5.$iTest.3.4 { 460 B finish 461 } {SQLITE_OK} 462 integrity_check backup-5.$iTest.3.5 db2 463 test_contents backup-5.$iTest.3.6 db main db2 main 464 465 do_test backup-5.$iTest.4.1 { 466 execsql { UPDATE t1 SET b = randstr(1000,1000) } 467 } {} 468 do_test backup-5.$iTest.4.2 { 469 sqlite3_backup B db2 main db main 470 B step 50 471 } {SQLITE_OK} 472 do_test backup-5.$iTest.4.3 { 473 execsql { 474 PRAGMA page_size = 2048; 475 VACUUM; 476 } $writer 477 B step 5000 478 } {SQLITE_DONE} 479 do_test backup-5.$iTest.4.4 { 480 B finish 481 } {SQLITE_OK} 482 integrity_check backup-5.$iTest.4.5 db2 483 test_contents backup-5.$iTest.4.6 db main db2 main 484 485 catch {db close} 486 catch {db2 close} 487 catch {db3 close} 488 catch { file delete -force -- bak.db } 489 sqlite3 db2 bak.db 490 catch { file delete -force -- $file } 491 sqlite3 db $file 492 sqlite3 db3 $file 493 do_test backup-5.$iTest.5.1 { 494 execsql { 495 PRAGMA auto_vacuum = incremental; 496 BEGIN; 497 CREATE TABLE t1(a, b); 498 CREATE INDEX i1 ON t1(a, b); 499 INSERT INTO t1 VALUES(1, randstr(1000,1000)); 500 INSERT INTO t1 VALUES(2, randstr(1000,1000)); 501 INSERT INTO t1 VALUES(3, randstr(1000,1000)); 502 INSERT INTO t1 VALUES(4, randstr(1000,1000)); 503 INSERT INTO t1 VALUES(5, randstr(1000,1000)); 504 COMMIT; 505 } 506 } {} 507 do_test backup-5.$iTest.5.2 { 508 sqlite3_backup B db2 main db main 509 B step 8 510 } {SQLITE_OK} 511 do_test backup-5.$iTest.5.3 { 512 execsql { 513 DELETE FROM t1; 514 PRAGMA incremental_vacuum; 515 } $writer 516 B step 50 517 } {SQLITE_DONE} 518 do_test backup-5.$iTest.5.4 { 519 B finish 520 } {SQLITE_OK} 521 integrity_check backup-5.$iTest.5.5 db2 522 catch {db close} 523 catch {db2 close} 524 catch {db3 close} 525} 526# 527# End of backup-5.* tests. 528#--------------------------------------------------------------------- 529 530#--------------------------------------------------------------------- 531# Test the sqlite3_backup_remaining() and backup_pagecount() APIs. 532# 533do_test backup-6.1 { 534 catch { file delete -force -- test.db } 535 catch { file delete -force -- test2.db } 536 sqlite3 db test.db 537 sqlite3 db2 test2.db 538 execsql { 539 BEGIN; 540 CREATE TABLE t1(a, b); 541 CREATE INDEX i1 ON t1(a, b); 542 INSERT INTO t1 VALUES(1, randstr(1000,1000)); 543 INSERT INTO t1 VALUES(2, randstr(1000,1000)); 544 INSERT INTO t1 VALUES(3, randstr(1000,1000)); 545 INSERT INTO t1 VALUES(4, randstr(1000,1000)); 546 INSERT INTO t1 VALUES(5, randstr(1000,1000)); 547 COMMIT; 548 } 549} {} 550do_test backup-6.2 { 551 set nTotal [expr {[file size test.db]/1024}] 552 sqlite3_backup B db2 main db main 553 B step 1 554} {SQLITE_OK} 555do_test backup-6.3 { 556 B pagecount 557} $nTotal 558do_test backup-6.4 { 559 B remaining 560} [expr $nTotal-1] 561do_test backup-6.5 { 562 B step 5 563 list [B remaining] [B pagecount] 564} [list [expr $nTotal-6] $nTotal] 565do_test backup-6.6 { 566 execsql { CREATE TABLE t2(a PRIMARY KEY, b) } 567 B step 1 568 list [B remaining] [B pagecount] 569} [list [expr $nTotal-5] [expr $nTotal+2]] 570 571do_test backup-6.X { 572 B finish 573} {SQLITE_OK} 574 575catch {db close} 576catch {db2 close} 577 578#--------------------------------------------------------------------- 579# Test cases backup-7.* test that SQLITE_BUSY and SQLITE_LOCKED errors 580# are returned correctly: 581# 582# backup-7.1.*: Source database is externally locked (return SQLITE_BUSY). 583# 584# backup-7.2.*: Attempt to step the backup process while a 585# write-transaction is underway on the source pager (return 586# SQLITE_LOCKED). 587# 588# backup-7.3.*: Destination database is externally locked (return SQLITE_BUSY). 589# 590do_test backup-7.0 { 591 catch { file delete -force -- test.db } 592 catch { file delete -force -- test2.db } 593 sqlite3 db2 test2.db 594 sqlite3 db test.db 595 sqlite3 db3 test.db 596 execsql { 597 CREATE TABLE t1(a, b); 598 CREATE INDEX i1 ON t1(a, b); 599 INSERT INTO t1 VALUES(1, randstr(1000,1000)); 600 INSERT INTO t1 SELECT a+ 1, randstr(1000,1000) FROM t1; 601 INSERT INTO t1 SELECT a+ 2, randstr(1000,1000) FROM t1; 602 INSERT INTO t1 SELECT a+ 4, randstr(1000,1000) FROM t1; 603 INSERT INTO t1 SELECT a+ 8, randstr(1000,1000) FROM t1; 604 INSERT INTO t1 SELECT a+16, randstr(1000,1000) FROM t1; 605 INSERT INTO t1 SELECT a+32, randstr(1000,1000) FROM t1; 606 INSERT INTO t1 SELECT a+64, randstr(1000,1000) FROM t1; 607 } 608} {} 609 610do_test backup-7.1.1 { 611 sqlite3_backup B db2 main db main 612 B step 5 613} {SQLITE_OK} 614do_test backup-7.2.1 { 615 execsql { 616 BEGIN; 617 INSERT INTO t1 VALUES(1, 4); 618 } 619} {} 620do_test backup-7.2.3 { 621 execsql { ROLLBACK } 622 B step 5000 623} {SQLITE_DONE} 624do_test backup-7.2.4 { 625 B finish 626} {SQLITE_OK} 627test_contents backup-7.2.5 db main db2 main 628integrity_check backup-7.3.6 db2 629 630do_test backup-7.3.1 { 631 db2 close 632 db3 close 633 file delete -force -- test2.db 634 sqlite3 db2 test2.db 635 sqlite3 db3 test2.db 636 637 sqlite3_backup B db2 main db main 638 execsql { BEGIN ; CREATE TABLE t2(a, b); COMMIT; } db3 639 640 B step 5 641} {SQLITE_BUSY} 642do_test backup-7.3.2 { 643 catch { db3 close } 644 B step 5000 645} {SQLITE_DONE} 646do_test backup-7.3.3 { 647 B finish 648} {SQLITE_OK} 649test_contents backup-7.3.4 db main db2 main 650integrity_check backup-7.3.5 db2 651catch { db2 close } 652 653#----------------------------------------------------------------------- 654# The following tests, backup-8.*, test attaching multiple backup 655# processes to the same source database. Also, reading from the source 656# database while a read transaction is active. 657# 658# These tests reuse the database "test.db" left over from backup-7.*. 659# 660do_test backup-8.1 { 661 catch { file delete -force -- test2.db } 662 catch { file delete -force -- test3.db } 663 sqlite3 db2 test2.db 664 sqlite3 db3 test3.db 665 666 sqlite3_backup B2 db2 main db main 667 sqlite3_backup B3 db3 main db main 668 list [B2 finish] [B3 finish] 669} {SQLITE_OK SQLITE_OK} 670do_test backup-8.2 { 671 sqlite3_backup B3 db3 main db main 672 sqlite3_backup B2 db2 main db main 673 list [B2 finish] [B3 finish] 674} {SQLITE_OK SQLITE_OK} 675do_test backup-8.3 { 676 sqlite3_backup B2 db2 main db main 677 sqlite3_backup B3 db3 main db main 678 B2 step 5 679} {SQLITE_OK} 680do_test backup-8.4 { 681 execsql { 682 BEGIN; 683 SELECT * FROM sqlite_master; 684 } 685 B3 step 5 686} {SQLITE_OK} 687do_test backup-8.5 { 688 list [B3 step 5000] [B3 finish] 689} {SQLITE_DONE SQLITE_OK} 690do_test backup-8.6 { 691 list [B2 step 5000] [B2 finish] 692} {SQLITE_DONE SQLITE_OK} 693test_contents backup-8.7 db main db2 main 694test_contents backup-8.8 db main db3 main 695do_test backup-8.9 { 696 execsql { PRAGMA lock_status } 697} {main shared temp closed} 698do_test backup-8.10 { 699 execsql COMMIT 700} {} 701catch { db2 close } 702catch { db3 close } 703 704#----------------------------------------------------------------------- 705# The following tests, backup-9.*, test that: 706# 707# * Passing 0 as an argument to sqlite3_backup_step() means no pages 708# are backed up (backup-9.1.*), and 709# * Passing a negative value as an argument to sqlite3_backup_step() means 710# all pages are backed up (backup-9.2.*). 711# 712# These tests reuse the database "test.db" left over from backup-7.*. 713# 714do_test backup-9.1.1 { 715 sqlite3 db2 test2.db 716 sqlite3_backup B db2 main db main 717 B step 1 718} {SQLITE_OK} 719do_test backup-9.1.2 { 720 set nRemaining [B remaining] 721 expr {$nRemaining>100} 722} {1} 723do_test backup-9.1.3 { 724 B step 0 725} {SQLITE_OK} 726do_test backup-9.1.4 { 727 B remaining 728} $nRemaining 729 730do_test backup-9.2.1 { 731 B step -1 732} {SQLITE_DONE} 733do_test backup-9.2.2 { 734 B remaining 735} {0} 736do_test backup-9.2.3 { 737 B finish 738} {SQLITE_OK} 739catch {db2 close} 740 741ifcapable memorymanage { 742 db close 743 file delete -force -- test.db 744 file delete -force -- bak.db 745 746 sqlite3 db test.db 747 sqlite3 db2 test.db 748 sqlite3 db3 bak.db 749 750 do_test backup-10.1.1 { 751 execsql { 752 BEGIN; 753 CREATE TABLE t1(a, b); 754 INSERT INTO t1 VALUES(1, randstr(1000,1000)); 755 INSERT INTO t1 VALUES(2, randstr(1000,1000)); 756 INSERT INTO t1 VALUES(3, randstr(1000,1000)); 757 INSERT INTO t1 VALUES(4, randstr(1000,1000)); 758 INSERT INTO t1 VALUES(5, randstr(1000,1000)); 759 CREATE INDEX i1 ON t1(a, b); 760 COMMIT; 761 } 762 } {} 763 do_test backup-10.1.2 { 764 sqlite3_backup B db3 main db2 main 765 B step 5 766 } {SQLITE_OK} 767 do_test backup-10.1.3 { 768 execsql { 769 UPDATE t1 SET b = randstr(500,500); 770 } 771 } {} 772 sqlite3_release_memory [expr 1024*1024] 773 do_test backup-10.1.3 { 774 B step 50 775 } {SQLITE_DONE} 776 do_test backup-10.1.4 { 777 B finish 778 } {SQLITE_OK} 779 do_test backup-10.1.5 { 780 execsql { PRAGMA integrity_check } db3 781 } {ok} 782 783 db2 close 784 db3 close 785} 786 787 788#----------------------------------------------------------------------- 789# Test that if the database is written to via the same database handle being 790# used as the source by a backup operation: 791# 792# 10.1.*: If the db is in-memory, the backup is restarted. 793# 10.2.*: If the db is a file, the backup is restarted. 794# 10.3.*: If the db is in-memory, and not updated, the backup is not 795# restarted 796# 10.4.*: If the db is a file,and not updated, the backup is not 797# restarted 798# 799db close 800file delete -force -- test.db test.db-journal 801foreach {tn file update rc} { 802 1 test.db 1 SQLITE_OK 803 2 :memory: 1 SQLITE_OK 804 1 test.db 0 SQLITE_DONE 805 2 :memory: 0 SQLITE_DONE 806} { 807 do_test backup-10.$tn.1 { 808 sqlite3 db $file 809 execsql { 810 DROP TABLE IF EXISTS t1; 811 CREATE TABLE t1(a INTEGER PRIMARY KEY, b BLOB); 812 BEGIN; 813 INSERT INTO t1 VALUES(NULL, randomblob(200)); 814 INSERT INTO t1 SELECT NULL, randomblob(200) FROM t1; 815 INSERT INTO t1 SELECT NULL, randomblob(200) FROM t1; 816 INSERT INTO t1 SELECT NULL, randomblob(200) FROM t1; 817 INSERT INTO t1 SELECT NULL, randomblob(200) FROM t1; 818 INSERT INTO t1 SELECT NULL, randomblob(200) FROM t1; 819 INSERT INTO t1 SELECT NULL, randomblob(200) FROM t1; 820 INSERT INTO t1 SELECT NULL, randomblob(200) FROM t1; 821 INSERT INTO t1 SELECT NULL, randomblob(200) FROM t1; 822 COMMIT; 823 SELECT count(*) FROM t1; 824 } 825 } {256} 826 827 do_test backup-10.$tn.3 { 828 file delete -force -- bak.db bak.db-journal 829 sqlite3 db2 bak.db 830 sqlite3_backup B db2 main db main 831 B step 50 832 } {SQLITE_OK} 833 834 if { $update == 1 } { 835 do_test backup-10.$tn.4 { 836 execsql { UPDATE t1 SET b = randomblob(200) WHERE a IN (1, 250) } 837 } {} 838 } 839 840 do_test backup-10.$tn.5 { 841 B step 50 842 } $rc 843 844 do_test backup-10.$tn.6 { 845 B finish 846 } {SQLITE_OK} 847 848 db2 close 849} 850 851finish_test 852