File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / sqlite3 / test / backup.test
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 17:04:16 2012 UTC (12 years, 4 months ago) by misho
Branches: sqlite3, MAIN
CVS tags: v3_7_10, HEAD
sqlite3

    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.1.1.1 2012/02/21 17:04:16 misho Exp $
   15: 
   16: set testdir [file dirname $argv0]
   17: source $testdir/tester.tcl
   18: 
   19: do_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: 
   47: proc data_checksum {db file} { $db one "SELECT md5sum(a, b) FROM ${file}.t1" }
   48: proc 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: 
   55: do_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: #
   71: test_contents backup-1.2 db main db main
   72: 
   73: # Check that it is possible to create and finish backup operations.
   74: #
   75: do_test backup-1.3.1 {
   76:   delete_file test2.db
   77:   sqlite3 db2 test2.db
   78:   sqlite3_backup B db2 main db main
   79: } {B}
   80: do_test backup-1.3.2 {
   81:   B finish
   82: } {SQLITE_OK}
   83: do_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: # 
   90: do_test backup-1.4.1 {
   91:   sqlite3_backup B db2 main db main
   92: } {B}
   93: do_test backup-1.4.2 {
   94:   B step 200
   95: } {SQLITE_DONE}
   96: do_test backup-1.4.3 {
   97:   B finish
   98: } {SQLITE_OK}
   99: do_test backup-1.4.4 {
  100:   info commands B
  101: } {}
  102: test_contents backup-1.4.5 db2 main db main
  103: db close
  104: db2 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: #
  146: set iTest 1
  147: foreach zSrcFile {test.db :memory:} {
  148: foreach zDestFile {test2.db :memory:} {
  149: foreach 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: }] {
  166: foreach rows_dest {0 3 10} {
  167: foreach pgsz_dest {512 1024 2048} {
  168: foreach nPagePerStep {1 200} {
  169: 
  170:   # Open the databases.
  171:   catch { delete_file test.db }
  172:   catch { delete_file 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:       BEGIN;
  195:       CREATE TABLE t1(a, b);
  196:       CREATE INDEX i1 ON t1(a, b);
  197:       INSERT INTO t1 VALUES(1, randstr(1000,1000));
  198:       INSERT INTO t1 VALUES(2, randstr(1000,1000));
  199:       INSERT INTO t1 VALUES(3, randstr(1000,1000));
  200:       INSERT INTO t1 VALUES(4, randstr(1000,1000));
  201:       INSERT INTO t1 VALUES(5, randstr(1000,1000));
  202:       COMMIT;
  203:     }
  204:     
  205:     
  206: 
  207:     # Set up the content of the target database.
  208:     execsql "PRAGMA ${file_dest}.page_size = ${pgsz_dest}" $db_dest
  209:     if {$rows_dest != 0} {
  210:       execsql "
  211:         BEGIN; 
  212:         CREATE TABLE ${file_dest}.t1(a, b);
  213:         CREATE INDEX ${file_dest}.i1 ON t1(a, b);
  214:       " $db_dest
  215:       for {set ii 0} {$ii < $rows_dest} {incr ii} {
  216:         execsql "
  217:           INSERT INTO ${file_dest}.t1 VALUES(1, randstr(1000,1000))
  218:         " $db_dest
  219:       }
  220:     }
  221:   
  222:     # Backup the source database.
  223:     do_test backup-2.$iTest.1 {
  224:       sqlite3_backup B $db_dest $file_dest db main
  225:       while {[B step $nPagePerStep]=="SQLITE_OK"} {}
  226:       B finish
  227:     } {SQLITE_OK}
  228:     
  229:     # Run integrity check on the backup.
  230:     do_test backup-2.$iTest.2 {
  231:       execsql "PRAGMA ${file_dest}.integrity_check" $db_dest
  232:     } {ok}
  233:   
  234:     test_contents backup-2.$iTest.3 db main $db_dest $file_dest
  235:   
  236:   }
  237: 
  238:   db close
  239:   catch {db2 close}
  240:   incr iTest
  241: 
  242: } } } } } }
  243: #
  244: # End of backup-2.* tests.
  245: #---------------------------------------------------------------------
  246: 
  247: #---------------------------------------------------------------------
  248: # These tests, backup-3.*, ensure that nothing goes wrong if either 
  249: # the source or destination database are large enough to include the
  250: # the locking-page (the page that contains the range of bytes that
  251: # the locks are applied to). These tests assume that the pending
  252: # byte is at offset 0x00010000 (64KB offset), as set by tester.tcl, 
  253: # not at the 1GB offset as it usually is.
  254: #
  255: # The test procedure is as follows (same procedure as used for 
  256: # the backup-2.* tests):
  257: #
  258: #   1) Populate the source database.
  259: #   2) Populate the destination database.
  260: #   3) Run the backup to completion. (backup-3.*.1)
  261: #   4) Integrity check the destination db. (backup-3.*.2)
  262: #   5) Check that the contents of the destination db is the same as that
  263: #      of the source db. (backup-3.*.3)
  264: #
  265: # The test procedure is run with the following parameters varied: 
  266: #
  267: #   * Source database includes pending-byte page.
  268: #   * Source database does not include pending-byte page.
  269: #
  270: #   * Target database includes pending-byte page.
  271: #   * Target database does not include pending-byte page.
  272: #
  273: #   * Target database page-size is the same as the source, OR
  274: #   * Target database page-size is larger than the source, OR
  275: #   * Target database page-size is smaller than the source.
  276: #
  277: set iTest 1
  278: foreach nSrcPg {10 64 65 66 100} {
  279: foreach nDestRow {10 100} {
  280: foreach nDestPgsz {512 1024 2048 4096} {
  281: 
  282:   catch { delete_file test.db }
  283:   catch { delete_file test2.db }
  284:   sqlite3 db test.db
  285:   sqlite3 db2 test2.db
  286: 
  287:   # Set up the content of the two databases.
  288:   #
  289:   execsql { PRAGMA page_size = 1024 }
  290:   execsql "PRAGMA page_size = $nDestPgsz" db2
  291:   foreach db {db db2} {
  292:     execsql {
  293:       BEGIN; 
  294:       CREATE TABLE t1(a, b);
  295:       CREATE INDEX i1 ON t1(a, b);
  296:       COMMIT;
  297:     } $db
  298:   }
  299:   while {[file size test.db]/1024 < $nSrcPg} {
  300:     execsql { INSERT INTO t1 VALUES($ii, randstr(200,200)) }
  301:   }
  302: 
  303:   for {set ii 0} {$ii < $nDestRow} {incr ii} {
  304:     execsql { INSERT INTO t1 VALUES($ii, randstr(1000,1000)) } db2
  305:   }
  306: 
  307:   # Backup the source database.
  308:   do_test backup-3.$iTest.1 {
  309:     sqlite3_backup B db main db2 main
  310:     while {[B step 10]=="SQLITE_OK"} {}
  311:     B finish
  312:   } {SQLITE_OK}
  313:     
  314:   # Run integrity check on the backup.
  315:   do_test backup-3.$iTest.2 {
  316:     execsql "PRAGMA integrity_check" db2
  317:   } {ok}
  318:   
  319:   test_contents backup-3.$iTest.3 db main db2 main
  320: 
  321:   db close
  322:   db2 close
  323:   incr iTest
  324: }
  325: }
  326: }
  327: 
  328: #--------------------------------------------------------------------
  329: do_test backup-3.$iTest.1 {
  330:   catch { forcedelete test.db }
  331:   catch { forcedelete test2.db }
  332:   sqlite3 db test.db
  333:   set iTab 1
  334: 
  335:   db eval { PRAGMA page_size = 512 }
  336:   while {[file size test.db] <= $::sqlite_pending_byte} {
  337:     db eval "CREATE TABLE t${iTab}(a, b, c)"
  338:     incr iTab
  339:   }
  340: 
  341:   sqlite3 db2 test2.db
  342:   db2 eval { PRAGMA page_size = 4096 }
  343:   while {[file size test2.db] < $::sqlite_pending_byte} {
  344:     db2 eval "CREATE TABLE t${iTab}(a, b, c)"
  345:     incr iTab
  346:   }
  347: 
  348:   sqlite3_backup B db2 main db main
  349:   B step -1
  350: } {SQLITE_DONE}
  351: 
  352: do_test backup-3.$iTest.2 {
  353:   B finish
  354: } {SQLITE_OK}
  355: 
  356: #
  357: # End of backup-3.* tests.
  358: #---------------------------------------------------------------------
  359: 
  360: 
  361: #---------------------------------------------------------------------
  362: # The following tests, backup-4.*, test various error conditions:
  363: # 
  364: # backup-4.1.*: Test invalid database names.
  365: #
  366: # backup-4.2.*: Test that the source database cannot be detached while 
  367: #               a backup is in progress.
  368: #
  369: # backup-4.3.*: Test that the source database handle cannot be closed
  370: #               while a backup is in progress.
  371: #
  372: # backup-4.4.*: Test an attempt to specify the same handle for the
  373: #               source and destination databases.
  374: #
  375: # backup-4.5.*: Test that an in-memory destination with a different
  376: #               page-size to the source database is an error.
  377: #
  378: sqlite3 db test.db
  379: sqlite3 db2 test2.db
  380: 
  381: do_test backup-4.1.1 {
  382:   catch { sqlite3_backup B db aux db2 main }
  383: } {1}
  384: do_test backup-4.1.2 {
  385:   sqlite3_errmsg db
  386: } {unknown database aux}
  387: do_test backup-4.1.3 {
  388:   catch { sqlite3_backup B db main db2 aux }
  389: } {1}
  390: do_test backup-4.1.4 {
  391:   sqlite3_errmsg db
  392: } {unknown database aux}
  393: 
  394: do_test backup-4.2.1 {
  395:   catch { forcedelete test3.db }
  396:   catch { forcedelete test4.db }
  397:   execsql { 
  398:     ATTACH 'test3.db' AS aux1;
  399:     CREATE TABLE aux1.t1(a, b);
  400:   }
  401:   execsql { 
  402:     ATTACH 'test4.db' AS aux2;
  403:     CREATE TABLE aux2.t2(a, b);
  404:   } db2
  405:   sqlite3_backup B db aux1 db2 aux2
  406: } {B}
  407: do_test backup-4.2.2 {
  408:   catchsql { DETACH aux2 } db2
  409: } {1 {database aux2 is locked}}
  410: do_test backup-4.2.3 {
  411:   B step 50
  412: } {SQLITE_DONE}
  413: do_test backup-4.2.4 {
  414:   B finish
  415: } {SQLITE_OK}
  416: 
  417: do_test backup-4.3.1 {
  418:   sqlite3_backup B db aux1 db2 aux2
  419: } {B}
  420: do_test backup-4.3.2 {
  421:   db2 cache flush
  422:   sqlite3_close db2
  423: } {SQLITE_BUSY}
  424: do_test backup-4.3.3 {
  425:   sqlite3_errmsg db2
  426: } {unable to close due to unfinished backup operation}
  427: do_test backup-4.3.4 {
  428:   B step 50
  429: } {SQLITE_DONE}
  430: do_test backup-4.3.5 {
  431:   B finish
  432: } {SQLITE_OK}
  433: 
  434: do_test backup-4.4.1 {
  435:   set rc [catch {sqlite3_backup B db main db aux1}]
  436:   list $rc [sqlite3_errcode db] [sqlite3_errmsg db]
  437: } {1 SQLITE_ERROR {source and destination must be distinct}}
  438: db close
  439: db2 close
  440: 
  441: do_test backup-4.5.1 {
  442:   catch { forcedelete test.db }
  443:   sqlite3 db test.db
  444:   sqlite3 db2 :memory:
  445:   execsql {
  446:     CREATE TABLE t1(a, b);
  447:     INSERT INTO t1 VALUES(1, 2);
  448:   }
  449:   execsql {
  450:     PRAGMA page_size = 4096;
  451:     CREATE TABLE t2(a, b);
  452:     INSERT INTO t2 VALUES(3, 4);
  453:   } db2
  454:   sqlite3_backup B db2 main db main
  455: } {B}
  456: do_test backup-4.5.2 {
  457:   B step 5000
  458: } {SQLITE_READONLY}
  459: do_test backup-4.5.3 {
  460:   B finish
  461: } {SQLITE_READONLY}
  462: 
  463: db close
  464: db2 close
  465: #
  466: # End of backup-5.* tests.
  467: #---------------------------------------------------------------------
  468: 
  469: #---------------------------------------------------------------------
  470: # The following tests, backup-5.*, test that the backup works properly
  471: # when the source database is modified during the backup. Test cases
  472: # are organized as follows:
  473: #
  474: # backup-5.x.1.*: Nothing special. Modify the database mid-backup.
  475: #
  476: # backup-5.x.2.*: Modify the database mid-backup so that one or more
  477: #                 pages are written out due to cache stress. Then 
  478: #                 rollback the transaction.
  479: #
  480: # backup-5.x.3.*: Database is vacuumed.
  481: #
  482: # backup-5.x.4.*: Database is vacuumed and the page-size modified.
  483: #
  484: # backup-5.x.5.*: Database is shrunk via incr-vacuum.
  485: #
  486: # Each test is run three times, in the following configurations:
  487: #
  488: #   1) Backing up file-to-file. The writer writes via an external pager.
  489: #   2) Backing up file-to-file. The writer writes via the same pager as
  490: #      is used by the backup operation.
  491: #   3) Backing up memory-to-file. 
  492: #
  493: set iTest 0
  494: forcedelete bak.db-wal
  495: foreach {writer file} {db test.db db3 test.db db :memory:} {
  496:   incr iTest
  497:   catch { delete_file bak.db }
  498:   sqlite3 db2 bak.db
  499:   catch { delete_file $file }
  500:   sqlite3 db $file
  501:   sqlite3 db3 $file
  502: 
  503:   do_test backup-5.$iTest.1.1 {
  504:     execsql {
  505:       BEGIN;
  506:       CREATE TABLE t1(a, b);
  507:       CREATE INDEX i1 ON t1(a, b);
  508:       INSERT INTO t1 VALUES(1, randstr(1000,1000));
  509:       INSERT INTO t1 VALUES(2, randstr(1000,1000));
  510:       INSERT INTO t1 VALUES(3, randstr(1000,1000));
  511:       INSERT INTO t1 VALUES(4, randstr(1000,1000));
  512:       INSERT INTO t1 VALUES(5, randstr(1000,1000));
  513:       COMMIT;
  514:     }
  515:     expr {[execsql {PRAGMA page_count}] > 10}
  516:   } {1}
  517:   do_test backup-5.$iTest.1.2 {
  518:     sqlite3_backup B db2 main db main
  519:     B step 5
  520:   } {SQLITE_OK}
  521:   do_test backup-5.$iTest.1.3 {
  522:     execsql { UPDATE t1 SET a = a + 1 } $writer
  523:     B step 50
  524:   } {SQLITE_DONE}
  525:   do_test backup-5.$iTest.1.4 {
  526:     B finish
  527:   } {SQLITE_OK} 
  528:   integrity_check backup-5.$iTest.1.5 db2
  529:   test_contents backup-5.$iTest.1.6 db main db2 main
  530: 
  531:   do_test backup-5.$iTest.2.1 {
  532:     execsql {
  533:       PRAGMA cache_size = 10;
  534:       BEGIN;
  535:       INSERT INTO t1 SELECT '', randstr(1000,1000) FROM t1;
  536:       INSERT INTO t1 SELECT '', randstr(1000,1000) FROM t1;
  537:       INSERT INTO t1 SELECT '', randstr(1000,1000) FROM t1;
  538:       INSERT INTO t1 SELECT '', randstr(1000,1000) FROM t1;
  539:       COMMIT;
  540:     }
  541:   } {}
  542:   do_test backup-5.$iTest.2.2 {
  543:     sqlite3_backup B db2 main db main
  544:     B step 50
  545:   } {SQLITE_OK}
  546:   do_test backup-5.$iTest.2.3 {
  547:     execsql { 
  548:       BEGIN;
  549:       UPDATE t1 SET a = a + 1;
  550:       ROLLBACK;
  551:     } $writer
  552:     B step 5000
  553:   } {SQLITE_DONE}
  554:   do_test backup-5.$iTest.2.4 {
  555:     B finish
  556:   } {SQLITE_OK} 
  557:   integrity_check backup-5.$iTest.2.5 db2
  558:   test_contents backup-5.$iTest.2.6 db main db2 main
  559: 
  560:   do_test backup-5.$iTest.3.1 {
  561:     execsql { UPDATE t1 SET b = randstr(1000,1000) }
  562:   } {}
  563:   do_test backup-5.$iTest.3.2 {
  564:     sqlite3_backup B db2 main db main
  565:     B step 50
  566:   } {SQLITE_OK}
  567:   do_test backup-5.$iTest.3.3 {
  568:     execsql { VACUUM } $writer
  569:     B step 5000
  570:   } {SQLITE_DONE}
  571:   do_test backup-5.$iTest.3.4 {
  572:     B finish
  573:   } {SQLITE_OK} 
  574:   integrity_check backup-5.$iTest.3.5 db2
  575:   test_contents backup-5.$iTest.3.6 db main db2 main
  576: 
  577:   do_test backup-5.$iTest.4.1 {
  578:     execsql { UPDATE t1 SET b = randstr(1000,1000) }
  579:   } {}
  580:   do_test backup-5.$iTest.4.2 {
  581:     sqlite3_backup B db2 main db main
  582:     B step 50
  583:   } {SQLITE_OK}
  584:   do_test backup-5.$iTest.4.3 {
  585:     execsql { 
  586:       PRAGMA page_size = 2048;
  587:       VACUUM;
  588:     } $writer
  589:     B step 5000
  590:   } {SQLITE_DONE}
  591:   do_test backup-5.$iTest.4.4 {
  592:     B finish
  593:   } {SQLITE_OK} 
  594:   integrity_check backup-5.$iTest.4.5 db2
  595:   test_contents backup-5.$iTest.4.6 db main db2 main
  596: 
  597:   catch {db close}
  598:   catch {db2 close}
  599:   catch {db3 close}
  600:   catch { delete_file bak.db }
  601:   sqlite3 db2 bak.db
  602:   catch { delete_file $file }
  603:   sqlite3 db $file
  604:   sqlite3 db3 $file
  605:   do_test backup-5.$iTest.5.1 {
  606:     execsql {
  607:       PRAGMA auto_vacuum = incremental;
  608:       BEGIN;
  609:       CREATE TABLE t1(a, b);
  610:       CREATE INDEX i1 ON t1(a, b);
  611:       INSERT INTO t1 VALUES(1, randstr(1000,1000));
  612:       INSERT INTO t1 VALUES(2, randstr(1000,1000));
  613:       INSERT INTO t1 VALUES(3, randstr(1000,1000));
  614:       INSERT INTO t1 VALUES(4, randstr(1000,1000));
  615:       INSERT INTO t1 VALUES(5, randstr(1000,1000));
  616:       COMMIT;
  617:     }
  618:   } {}
  619:   do_test backup-5.$iTest.5.2 {
  620:     sqlite3_backup B db2 main db main
  621:     B step 8
  622:   } {SQLITE_OK}
  623:   do_test backup-5.$iTest.5.3 {
  624:     execsql { 
  625:       DELETE FROM t1;
  626:       PRAGMA incremental_vacuum;
  627:     } $writer
  628:     B step 50
  629:   } {SQLITE_DONE}
  630:   do_test backup-5.$iTest.5.4 {
  631:     B finish
  632:   } {SQLITE_OK} 
  633:   integrity_check backup-5.$iTest.5.5 db2
  634:   test_contents backup-5.$iTest.5.6 db main db2 main
  635:   catch {db close}
  636:   catch {db2 close}
  637:   catch {db3 close}
  638: }
  639: #
  640: # End of backup-5.* tests.
  641: #---------------------------------------------------------------------
  642: 
  643: #---------------------------------------------------------------------
  644: # Test the sqlite3_backup_remaining() and backup_pagecount() APIs.
  645: #
  646: do_test backup-6.1 {
  647:   catch { forcedelete test.db }
  648:   catch { forcedelete test2.db }
  649:   sqlite3 db test.db
  650:   sqlite3 db2 test2.db
  651:   execsql {
  652:     BEGIN;
  653:     CREATE TABLE t1(a, b);
  654:     CREATE INDEX i1 ON t1(a, b);
  655:     INSERT INTO t1 VALUES(1, randstr(1000,1000));
  656:     INSERT INTO t1 VALUES(2, randstr(1000,1000));
  657:     INSERT INTO t1 VALUES(3, randstr(1000,1000));
  658:     INSERT INTO t1 VALUES(4, randstr(1000,1000));
  659:     INSERT INTO t1 VALUES(5, randstr(1000,1000));
  660:     COMMIT;
  661:   }
  662: } {}
  663: do_test backup-6.2 {
  664:   set nTotal [expr {[file size test.db]/1024}]
  665:   sqlite3_backup B db2 main db main
  666:   B step 1
  667: } {SQLITE_OK}
  668: do_test backup-6.3 {
  669:   B pagecount
  670: } $nTotal
  671: do_test backup-6.4 {
  672:   B remaining
  673: } [expr $nTotal-1]
  674: do_test backup-6.5 {
  675:   B step 5
  676:   list [B remaining] [B pagecount]
  677: } [list [expr $nTotal-6] $nTotal]
  678: do_test backup-6.6 {
  679:   execsql { CREATE TABLE t2(a PRIMARY KEY, b) }
  680:   B step 1
  681:   list [B remaining] [B pagecount]
  682: } [list [expr $nTotal-5] [expr $nTotal+2]]
  683: 
  684: do_test backup-6.X {
  685:   B finish
  686: } {SQLITE_OK}
  687: 
  688: catch {db close}
  689: catch {db2 close}
  690: 
  691: #---------------------------------------------------------------------
  692: # Test cases backup-7.* test that SQLITE_BUSY and SQLITE_LOCKED errors
  693: # are returned correctly:
  694: #
  695: # backup-7.1.*: Source database is externally locked (return SQLITE_BUSY).
  696: #
  697: # backup-7.2.*: Attempt to step the backup process while a 
  698: #               write-transaction is underway on the source pager (return
  699: #               SQLITE_LOCKED).
  700: #
  701: # backup-7.3.*: Destination database is externally locked (return SQLITE_BUSY).
  702: #
  703: do_test backup-7.0 {
  704:   catch { forcedelete test.db }
  705:   catch { forcedelete test2.db }
  706:   sqlite3 db2 test2.db
  707:   sqlite3 db test.db
  708:   execsql {
  709:     CREATE TABLE t1(a, b);
  710:     CREATE INDEX i1 ON t1(a, b);
  711:     INSERT INTO t1 VALUES(1, randstr(1000,1000));
  712:     INSERT INTO t1 SELECT a+ 1, randstr(1000,1000) FROM t1;
  713:     INSERT INTO t1 SELECT a+ 2, randstr(1000,1000) FROM t1;
  714:     INSERT INTO t1 SELECT a+ 4, randstr(1000,1000) FROM t1;
  715:     INSERT INTO t1 SELECT a+ 8, randstr(1000,1000) FROM t1;
  716:     INSERT INTO t1 SELECT a+16, randstr(1000,1000) FROM t1;
  717:     INSERT INTO t1 SELECT a+32, randstr(1000,1000) FROM t1;
  718:     INSERT INTO t1 SELECT a+64, randstr(1000,1000) FROM t1;
  719:   }
  720: } {}
  721: 
  722: do_test backup-7.1.1 {
  723:   sqlite3_backup B db2 main db main
  724:   B step 5
  725: } {SQLITE_OK}
  726: do_test backup-7.1.2 {
  727:   sqlite3 db3 test.db
  728:   execsql { BEGIN EXCLUSIVE } db3
  729:   B step 5
  730: } {SQLITE_BUSY}
  731: do_test backup-7.1.3 {
  732:   execsql { ROLLBACK } db3
  733:   B step 5
  734: } {SQLITE_OK}
  735: do_test backup-7.2.1 {
  736:   execsql { 
  737:     BEGIN;
  738:     INSERT INTO t1 VALUES(1, 4);
  739:   }
  740: } {}
  741: do_test backup-7.2.2 {
  742:   B step 5000
  743: } {SQLITE_BUSY}
  744: do_test backup-7.2.3 {
  745:   execsql { ROLLBACK }
  746:   B step 5000
  747: } {SQLITE_DONE}
  748: do_test backup-7.2.4 {
  749:   B finish
  750: } {SQLITE_OK}
  751: test_contents backup-7.2.5 db main db2 main
  752: integrity_check backup-7.3.6 db2
  753: 
  754: do_test backup-7.3.1 {
  755:   db2 close
  756:   db3 close
  757:   forcedelete test2.db
  758:   sqlite3 db2 test2.db
  759:   sqlite3 db3 test2.db
  760: 
  761:   sqlite3_backup B db2 main db main
  762:   execsql { BEGIN ; CREATE TABLE t2(a, b); } db3
  763: 
  764:   B step 5
  765: } {SQLITE_BUSY}
  766: do_test backup-7.3.2 {
  767:   execsql { COMMIT } db3
  768:   B step 5000
  769: } {SQLITE_DONE}
  770: do_test backup-7.3.3 {
  771:   B finish
  772: } {SQLITE_OK}
  773: test_contents backup-7.3.4 db main db2 main
  774: integrity_check backup-7.3.5 db2
  775: catch { db2 close }
  776: catch { db3 close }
  777: 
  778: #-----------------------------------------------------------------------
  779: # The following tests, backup-8.*, test attaching multiple backup
  780: # processes to the same source database. Also, reading from the source
  781: # database while a read transaction is active.
  782: #
  783: # These tests reuse the database "test.db" left over from backup-7.*.
  784: #
  785: do_test backup-8.1 {
  786:   catch { forcedelete test2.db }
  787:   catch { forcedelete test3.db }
  788:   sqlite3 db2 test2.db
  789:   sqlite3 db3 test3.db
  790: 
  791:   sqlite3_backup B2 db2 main db main
  792:   sqlite3_backup B3 db3 main db main
  793:   list [B2 finish] [B3 finish]
  794: } {SQLITE_OK SQLITE_OK}
  795: do_test backup-8.2 {
  796:   sqlite3_backup B3 db3 main db main
  797:   sqlite3_backup B2 db2 main db main
  798:   list [B2 finish] [B3 finish]
  799: } {SQLITE_OK SQLITE_OK}
  800: do_test backup-8.3 {
  801:   sqlite3_backup B2 db2 main db main
  802:   sqlite3_backup B3 db3 main db main
  803:   B2 step 5
  804: } {SQLITE_OK}
  805: do_test backup-8.4 {
  806:   execsql {
  807:     BEGIN;
  808:     SELECT * FROM sqlite_master;
  809:   }
  810:   B3 step 5
  811: } {SQLITE_OK}
  812: do_test backup-8.5 {
  813:   list [B3 step 5000] [B3 finish]
  814: } {SQLITE_DONE SQLITE_OK}
  815: do_test backup-8.6 {
  816:   list [B2 step 5000] [B2 finish]
  817: } {SQLITE_DONE SQLITE_OK}
  818: test_contents backup-8.7 db main db2 main
  819: test_contents backup-8.8 db main db3 main
  820: do_test backup-8.9 {
  821:   execsql { PRAGMA lock_status }
  822: } {main shared temp closed}
  823: do_test backup-8.10 {
  824:   execsql COMMIT
  825: } {}
  826: catch { db2 close }
  827: catch { db3 close }
  828: 
  829: #-----------------------------------------------------------------------
  830: # The following tests, backup-9.*, test that:
  831: # 
  832: #   * Passing 0 as an argument to sqlite3_backup_step() means no pages
  833: #     are backed up (backup-9.1.*), and 
  834: #   * Passing a negative value as an argument to sqlite3_backup_step() means 
  835: #     all pages are backed up (backup-9.2.*).
  836: #
  837: # These tests reuse the database "test.db" left over from backup-7.*.
  838: # 
  839: do_test backup-9.1.1 {
  840:   sqlite3 db2 test2.db
  841:   sqlite3_backup B db2 main db main
  842:   B step 1
  843: } {SQLITE_OK}
  844: do_test backup-9.1.2 {
  845:   set nRemaining [B remaining]
  846:   expr {$nRemaining>100}
  847: } {1}
  848: do_test backup-9.1.3 {
  849:   B step 0
  850: } {SQLITE_OK}
  851: do_test backup-9.1.4 {
  852:   B remaining
  853: } $nRemaining
  854: 
  855: do_test backup-9.2.1 {
  856:   B step -1
  857: } {SQLITE_DONE}
  858: do_test backup-9.2.2 {
  859:   B remaining
  860: } {0}
  861: do_test backup-9.2.3 {
  862:   B finish
  863: } {SQLITE_OK}
  864: catch {db2 close}
  865: 
  866: ifcapable memorymanage {
  867:   db close
  868:   forcedelete test.db
  869:   forcedelete bak.db
  870: 
  871:   sqlite3 db test.db
  872:   sqlite3 db2 test.db
  873:   sqlite3 db3 bak.db
  874: 
  875:   do_test backup-10.1.1 {
  876:     execsql {
  877:       BEGIN;
  878:       CREATE TABLE t1(a, b);
  879:       INSERT INTO t1 VALUES(1, randstr(1000,1000));
  880:       INSERT INTO t1 VALUES(2, randstr(1000,1000));
  881:       INSERT INTO t1 VALUES(3, randstr(1000,1000));
  882:       INSERT INTO t1 VALUES(4, randstr(1000,1000));
  883:       INSERT INTO t1 VALUES(5, randstr(1000,1000));
  884:       CREATE INDEX i1 ON t1(a, b);
  885:       COMMIT;
  886:     }
  887:   } {}
  888:   do_test backup-10.1.2 {
  889:     sqlite3_backup B db3 main db2 main
  890:     B step 5
  891:   } {SQLITE_OK}
  892:   do_test backup-10.1.3 {
  893:     execsql {
  894:       UPDATE t1 SET b = randstr(500,500);
  895:     }
  896:   } {}
  897:   sqlite3_release_memory [expr 1024*1024]
  898:   do_test backup-10.1.3 {
  899:     B step 50
  900:   } {SQLITE_DONE}
  901:   do_test backup-10.1.4 {
  902:     B finish
  903:   } {SQLITE_OK}
  904:   do_test backup-10.1.5 {
  905:     execsql { PRAGMA integrity_check } db3
  906:   } {ok}
  907: 
  908:   db2 close
  909:   db3 close
  910: }
  911: 
  912: 
  913: #-----------------------------------------------------------------------
  914: # Test that if the database is written to via the same database handle being
  915: # used as the source by a backup operation:
  916: #
  917: #   10.1.*: If the db is in-memory, the backup is restarted.
  918: #   10.2.*: If the db is a file, the backup is not restarted.
  919: #
  920: db close
  921: forcedelete test.db test.db-journal
  922: foreach {tn file rc} {
  923:   1 test.db  SQLITE_DONE
  924:   2 :memory: SQLITE_OK
  925: } {
  926:   do_test backup-10.$tn.1 {
  927:     sqlite3 db $file
  928:     execsql { 
  929:       CREATE TABLE t1(a INTEGER PRIMARY KEY, b BLOB);
  930:       BEGIN;
  931:         INSERT INTO t1 VALUES(NULL, randomblob(200));
  932:         INSERT INTO t1 SELECT NULL, randomblob(200) FROM t1;
  933:         INSERT INTO t1 SELECT NULL, randomblob(200) FROM t1;
  934:         INSERT INTO t1 SELECT NULL, randomblob(200) FROM t1;
  935:         INSERT INTO t1 SELECT NULL, randomblob(200) FROM t1;
  936:         INSERT INTO t1 SELECT NULL, randomblob(200) FROM t1;
  937:         INSERT INTO t1 SELECT NULL, randomblob(200) FROM t1;
  938:         INSERT INTO t1 SELECT NULL, randomblob(200) FROM t1;
  939:         INSERT INTO t1 SELECT NULL, randomblob(200) FROM t1;
  940:       COMMIT;
  941:       SELECT count(*) FROM t1;
  942:     }
  943:   } {256}
  944: 
  945:   do_test backup-10.$tn.2 {
  946:     set pgs [execsql {pragma page_count}]
  947:     expr {$pgs > 50 && $pgs < 75}
  948:   } {1}
  949: 
  950:   do_test backup-10.$tn.3 {
  951:     forcedelete bak.db bak.db-journal
  952:     sqlite3 db2 bak.db
  953:     sqlite3_backup B db2 main db main
  954:     B step 50
  955:   } {SQLITE_OK}
  956: 
  957:   do_test backup-10.$tn.4 {
  958:     execsql { UPDATE t1 SET b = randomblob(200) WHERE a IN (1, 250) }
  959:   } {}
  960: 
  961:   do_test backup-10.$tn.5 {
  962:     B step 50
  963:   } $rc
  964: 
  965:   do_test backup-10.$tn.6 {
  966:     B finish
  967:   } {SQLITE_OK}
  968: 
  969:   db2 close
  970: }
  971: 
  972: finish_test

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>