xref: /sqlite-3.40.0/test/backup.test (revision 92ecf306)
1dc2c4915Sdrh# 2009 January 30
20410302eSdanielk1977#
30410302eSdanielk1977# The author disclaims copyright to this source code.  In place of
40410302eSdanielk1977# a legal notice, here is a blessing:
50410302eSdanielk1977#
60410302eSdanielk1977#    May you do good and not evil.
70410302eSdanielk1977#    May you find forgiveness for yourself and forgive others.
80410302eSdanielk1977#    May you share freely, never taking more than you give.
90410302eSdanielk1977#
100410302eSdanielk1977#***********************************************************************
110410302eSdanielk1977# This file implements regression tests for SQLite library.  The
120410302eSdanielk1977# focus of this file is testing the sqlite3_backup_XXX API.
130410302eSdanielk1977#
14dda70fe3Sdrh# $Id: backup.test,v 1.11 2009/06/05 17:09:12 drh Exp $
150410302eSdanielk1977
160410302eSdanielk1977set testdir [file dirname $argv0]
170410302eSdanielk1977source $testdir/tester.tcl
180410302eSdanielk1977
1968928b6cSdando_not_use_codec
2068928b6cSdan
210410302eSdanielk1977#---------------------------------------------------------------------
220410302eSdanielk1977# Test organization:
230410302eSdanielk1977#
240410302eSdanielk1977# backup-1.*: Warm-body tests.
250410302eSdanielk1977#
260410302eSdanielk1977# backup-2.*: Test backup under various conditions. To and from in-memory
270410302eSdanielk1977#             databases. To and from empty/populated databases. etc.
280410302eSdanielk1977#
290410302eSdanielk1977# backup-3.*: Verify that the locking-page (pending byte page) is handled.
300410302eSdanielk1977#
310410302eSdanielk1977# backup-4.*: Test various error conditions.
320410302eSdanielk1977#
330410302eSdanielk1977# backup-5.*: Test the source database being modified during a backup.
340410302eSdanielk1977#
350410302eSdanielk1977# backup-6.*: Test the backup_remaining() and backup_pagecount() APIs.
360410302eSdanielk1977#
370410302eSdanielk1977# backup-7.*: Test SQLITE_BUSY and SQLITE_LOCKED errors.
380410302eSdanielk1977#
390410302eSdanielk1977# backup-8.*: Test multiple simultaneous backup operations.
400410302eSdanielk1977#
4103ab0357Sdanielk1977# backup-9.*: Test that passing a negative argument to backup_step() is
4203ab0357Sdanielk1977#             interpreted as "copy the whole file".
4303ab0357Sdanielk1977#
443306c4a9Sdan# backup-10.*: Test writing the source database mid backup.
453306c4a9Sdan#
460410302eSdanielk1977
470410302eSdanielk1977proc data_checksum {db file} { $db one "SELECT md5sum(a, b) FROM ${file}.t1" }
480410302eSdanielk1977proc test_contents {name db1 file1 db2 file2} {
490410302eSdanielk1977  $db2 eval {select * from sqlite_master}
500410302eSdanielk1977  $db1 eval {select * from sqlite_master}
510410302eSdanielk1977  set checksum [data_checksum $db2 $file2]
520410302eSdanielk1977  uplevel [list do_test $name [list data_checksum $db1 $file1] $checksum]
530410302eSdanielk1977}
540410302eSdanielk1977
550410302eSdanielk1977do_test backup-1.1 {
560410302eSdanielk1977  execsql {
570410302eSdanielk1977    BEGIN;
580410302eSdanielk1977    CREATE TABLE t1(a, b);
590410302eSdanielk1977    CREATE INDEX i1 ON t1(a, b);
600410302eSdanielk1977    INSERT INTO t1 VALUES(1, randstr(1000,1000));
610410302eSdanielk1977    INSERT INTO t1 VALUES(2, randstr(1000,1000));
620410302eSdanielk1977    INSERT INTO t1 VALUES(3, randstr(1000,1000));
630410302eSdanielk1977    INSERT INTO t1 VALUES(4, randstr(1000,1000));
640410302eSdanielk1977    INSERT INTO t1 VALUES(5, randstr(1000,1000));
650410302eSdanielk1977    COMMIT;
660410302eSdanielk1977  }
670410302eSdanielk1977} {}
680410302eSdanielk1977
690410302eSdanielk1977# Sanity check to verify that the [test_contents] proc works.
700410302eSdanielk1977#
710410302eSdanielk1977test_contents backup-1.2 db main db main
720410302eSdanielk1977
730410302eSdanielk1977# Check that it is possible to create and finish backup operations.
740410302eSdanielk1977#
750410302eSdanielk1977do_test backup-1.3.1 {
76fda06befSmistachkin  delete_file test2.db
770410302eSdanielk1977  sqlite3 db2 test2.db
780410302eSdanielk1977  sqlite3_backup B db2 main db main
790410302eSdanielk1977} {B}
800410302eSdanielk1977do_test backup-1.3.2 {
810410302eSdanielk1977  B finish
820410302eSdanielk1977} {SQLITE_OK}
830410302eSdanielk1977do_test backup-1.3.3 {
840410302eSdanielk1977  info commands B
850410302eSdanielk1977} {}
860410302eSdanielk1977
870410302eSdanielk1977# Simplest backup operation. Backup test.db to test2.db. test2.db is
880410302eSdanielk1977# initially empty. test.db uses the default page size.
890410302eSdanielk1977#
900410302eSdanielk1977do_test backup-1.4.1 {
910410302eSdanielk1977  sqlite3_backup B db2 main db main
920410302eSdanielk1977} {B}
930410302eSdanielk1977do_test backup-1.4.2 {
940410302eSdanielk1977  B step 200
950410302eSdanielk1977} {SQLITE_DONE}
960410302eSdanielk1977do_test backup-1.4.3 {
970410302eSdanielk1977  B finish
980410302eSdanielk1977} {SQLITE_OK}
990410302eSdanielk1977do_test backup-1.4.4 {
1000410302eSdanielk1977  info commands B
1010410302eSdanielk1977} {}
1020410302eSdanielk1977test_contents backup-1.4.5 db2 main db main
1030410302eSdanielk1977db close
1040410302eSdanielk1977db2 close
1050410302eSdanielk1977#
1060410302eSdanielk1977# End of backup-1.* tests.
1070410302eSdanielk1977#---------------------------------------------------------------------
1080410302eSdanielk1977
1090410302eSdanielk1977
1100410302eSdanielk1977#---------------------------------------------------------------------
1110410302eSdanielk1977# The following tests, backup-2.*, are based on the following procedure:
1120410302eSdanielk1977#
1130410302eSdanielk1977#   1) Populate the source database.
1140410302eSdanielk1977#   2) Populate the destination database.
1150410302eSdanielk1977#   3) Run the backup to completion. (backup-2.*.1)
1160410302eSdanielk1977#   4) Integrity check the destination db. (backup-2.*.2)
1170410302eSdanielk1977#   5) Check that the contents of the destination db is the same as that
1180410302eSdanielk1977#      of the source db. (backup-2.*.3)
1190410302eSdanielk1977#
1200410302eSdanielk1977# The test is run with all possible combinations of the following
1210410302eSdanielk1977# input parameters, except that if the destination is an in-memory
1220410302eSdanielk1977# database, the only page size tested is 1024 bytes (the same as the
1230410302eSdanielk1977# source page-size).
1240410302eSdanielk1977#
1250410302eSdanielk1977#   * Source database is an in-memory database, OR
1260410302eSdanielk1977#   * Source database is a file-backed database.
1270410302eSdanielk1977#
1280410302eSdanielk1977#   * Target database is an in-memory database, OR
1290410302eSdanielk1977#   * Target database is a file-backed database.
1300410302eSdanielk1977#
1310410302eSdanielk1977#   * Destination database is a main file, OR
1320410302eSdanielk1977#   * Destination database is an attached file, OR
1330410302eSdanielk1977#   * Destination database is a temp database.
1340410302eSdanielk1977#
1350410302eSdanielk1977#   * Target database is empty (zero bytes), OR
1360410302eSdanielk1977#   * Target database is larger than the source, OR
1370410302eSdanielk1977#   * Target database is smaller than the source.
1380410302eSdanielk1977#
1390410302eSdanielk1977#   * Target database page-size is the same as the source, OR
1400410302eSdanielk1977#   * Target database page-size is larger than the source, OR
1410410302eSdanielk1977#   * Target database page-size is smaller than the source.
1420410302eSdanielk1977#
1430410302eSdanielk1977#   * Each call to step copies a single page, OR
1440410302eSdanielk1977#   * A single call to step copies the entire source database.
1450410302eSdanielk1977#
1460410302eSdanielk1977set iTest 1
1470410302eSdanielk1977foreach zSrcFile {test.db :memory:} {
1480410302eSdanielk1977foreach zDestFile {test2.db :memory:} {
1490410302eSdanielk1977foreach zOpenScript [list {
1500410302eSdanielk1977  sqlite3 db $zSrcFile
1510410302eSdanielk1977  sqlite3 db2 $zSrcFile
1520410302eSdanielk1977  db2 eval "ATTACH '$zDestFile' AS bak"
1530410302eSdanielk1977  set db_dest db2
1540410302eSdanielk1977  set file_dest bak
1550410302eSdanielk1977} {
1560410302eSdanielk1977  sqlite3 db $zSrcFile
1570410302eSdanielk1977  sqlite3 db2 $zDestFile
1580410302eSdanielk1977  set db_dest db2
1590410302eSdanielk1977  set file_dest main
1600410302eSdanielk1977} {
1610410302eSdanielk1977  sqlite3 db $zSrcFile
1620410302eSdanielk1977  sqlite3 db2 $zDestFile
1630410302eSdanielk1977  set db_dest db2
1640410302eSdanielk1977  set file_dest temp
1650410302eSdanielk1977}] {
1660410302eSdanielk1977foreach rows_dest {0 3 10} {
1679bf01363Sdanforeach pgsz_dest {512 1024 2048 4096} {
1680410302eSdanielk1977foreach nPagePerStep {1 200} {
1690410302eSdanielk1977
1700410302eSdanielk1977  # Open the databases.
171fda06befSmistachkin  catch { delete_file test.db }
172fda06befSmistachkin  catch { delete_file test2.db }
1730410302eSdanielk1977  eval $zOpenScript
1740410302eSdanielk1977
1753d781c21Sdanielk1977  # Set to true if copying to an in-memory destination. Copying to an
1763d781c21Sdanielk1977  # in-memory destination is only possible if the initial destination
1773d781c21Sdanielk1977  # page size is the same as the source page size (in this case 1024 bytes).
1783d781c21Sdanielk1977  #
1799bf01363Sdan  set isMemDest [expr { $zDestFile eq ":memory:" || $file_dest eq "temp" }]
1800410302eSdanielk1977
1810410302eSdanielk1977  if 0 {
1820410302eSdanielk1977    puts -nonewline "Test $iTest: src=$zSrcFile dest=$zDestFile"
1830410302eSdanielk1977    puts -nonewline " (as $db_dest.$file_dest)"
1840410302eSdanielk1977    puts -nonewline " rows_dest=$rows_dest pgsz_dest=$pgsz_dest"
1850410302eSdanielk1977    puts ""
1860410302eSdanielk1977  }
1870410302eSdanielk1977
1889bf01363Sdan  if { $isMemDest==0 || $pgsz_dest==1024 || $rows_dest==0 } {
1899bf01363Sdan
1900410302eSdanielk1977    # Set up the content of the source database.
1910410302eSdanielk1977    execsql {
1923d781c21Sdanielk1977      PRAGMA page_size = 1024;
1930410302eSdanielk1977      BEGIN;
1940410302eSdanielk1977      CREATE TABLE t1(a, b);
1950410302eSdanielk1977      CREATE INDEX i1 ON t1(a, b);
1960410302eSdanielk1977      INSERT INTO t1 VALUES(1, randstr(1000,1000));
1970410302eSdanielk1977      INSERT INTO t1 VALUES(2, randstr(1000,1000));
1980410302eSdanielk1977      INSERT INTO t1 VALUES(3, randstr(1000,1000));
1990410302eSdanielk1977      INSERT INTO t1 VALUES(4, randstr(1000,1000));
2000410302eSdanielk1977      INSERT INTO t1 VALUES(5, randstr(1000,1000));
2010410302eSdanielk1977      COMMIT;
2020410302eSdanielk1977    }
2030410302eSdanielk1977
2040410302eSdanielk1977
2050410302eSdanielk1977
2060410302eSdanielk1977    # Set up the content of the target database.
2070410302eSdanielk1977    execsql "PRAGMA ${file_dest}.page_size = ${pgsz_dest}" $db_dest
2080410302eSdanielk1977    if {$rows_dest != 0} {
2090410302eSdanielk1977      execsql "
2100410302eSdanielk1977        BEGIN;
2110410302eSdanielk1977        CREATE TABLE ${file_dest}.t1(a, b);
2120410302eSdanielk1977        CREATE INDEX ${file_dest}.i1 ON t1(a, b);
2130410302eSdanielk1977      " $db_dest
2140410302eSdanielk1977      for {set ii 0} {$ii < $rows_dest} {incr ii} {
2150410302eSdanielk1977        execsql "
2160410302eSdanielk1977          INSERT INTO ${file_dest}.t1 VALUES(1, randstr(1000,1000))
2170410302eSdanielk1977        " $db_dest
2180410302eSdanielk1977      }
219fad01993Sdan      execsql COMMIT $db_dest
2200410302eSdanielk1977    }
2210410302eSdanielk1977
2220410302eSdanielk1977    # Backup the source database.
2230410302eSdanielk1977    do_test backup-2.$iTest.1 {
2240410302eSdanielk1977      sqlite3_backup B $db_dest $file_dest db main
2250410302eSdanielk1977      while {[B step $nPagePerStep]=="SQLITE_OK"} {}
2260410302eSdanielk1977      B finish
2270410302eSdanielk1977    } {SQLITE_OK}
2280410302eSdanielk1977
2290410302eSdanielk1977    # Run integrity check on the backup.
2300410302eSdanielk1977    do_test backup-2.$iTest.2 {
2310410302eSdanielk1977      execsql "PRAGMA ${file_dest}.integrity_check" $db_dest
2320410302eSdanielk1977    } {ok}
2330410302eSdanielk1977
2340410302eSdanielk1977    test_contents backup-2.$iTest.3 db main $db_dest $file_dest
2350410302eSdanielk1977
2360410302eSdanielk1977  }
2370410302eSdanielk1977
2380410302eSdanielk1977  db close
2390410302eSdanielk1977  catch {db2 close}
2400410302eSdanielk1977  incr iTest
2410410302eSdanielk1977
2420410302eSdanielk1977} } } } } }
2430410302eSdanielk1977#
2440410302eSdanielk1977# End of backup-2.* tests.
2450410302eSdanielk1977#---------------------------------------------------------------------
2460410302eSdanielk1977
2470410302eSdanielk1977#---------------------------------------------------------------------
2480410302eSdanielk1977# These tests, backup-3.*, ensure that nothing goes wrong if either
2490410302eSdanielk1977# the source or destination database are large enough to include the
2500410302eSdanielk1977# the locking-page (the page that contains the range of bytes that
2510410302eSdanielk1977# the locks are applied to). These tests assume that the pending
2520410302eSdanielk1977# byte is at offset 0x00010000 (64KB offset), as set by tester.tcl,
2530410302eSdanielk1977# not at the 1GB offset as it usually is.
2540410302eSdanielk1977#
2550410302eSdanielk1977# The test procedure is as follows (same procedure as used for
2560410302eSdanielk1977# the backup-2.* tests):
2570410302eSdanielk1977#
2580410302eSdanielk1977#   1) Populate the source database.
2590410302eSdanielk1977#   2) Populate the destination database.
2600410302eSdanielk1977#   3) Run the backup to completion. (backup-3.*.1)
2610410302eSdanielk1977#   4) Integrity check the destination db. (backup-3.*.2)
2620410302eSdanielk1977#   5) Check that the contents of the destination db is the same as that
2630410302eSdanielk1977#      of the source db. (backup-3.*.3)
2640410302eSdanielk1977#
2650410302eSdanielk1977# The test procedure is run with the following parameters varied:
2660410302eSdanielk1977#
2670410302eSdanielk1977#   * Source database includes pending-byte page.
2680410302eSdanielk1977#   * Source database does not include pending-byte page.
2690410302eSdanielk1977#
2700410302eSdanielk1977#   * Target database includes pending-byte page.
2710410302eSdanielk1977#   * Target database does not include pending-byte page.
2720410302eSdanielk1977#
2730410302eSdanielk1977#   * Target database page-size is the same as the source, OR
2740410302eSdanielk1977#   * Target database page-size is larger than the source, OR
2750410302eSdanielk1977#   * Target database page-size is smaller than the source.
2760410302eSdanielk1977#
2770410302eSdanielk1977set iTest 1
2783d0cbc33Sdanielk1977foreach nSrcPg {10 64 65 66 100} {
2790410302eSdanielk1977foreach nDestRow {10 100} {
2800410302eSdanielk1977foreach nDestPgsz {512 1024 2048 4096} {
2810410302eSdanielk1977
282fda06befSmistachkin  catch { delete_file test.db }
283fda06befSmistachkin  catch { delete_file test2.db }
2840410302eSdanielk1977  sqlite3 db test.db
2850410302eSdanielk1977  sqlite3 db2 test2.db
2860410302eSdanielk1977
2870410302eSdanielk1977  # Set up the content of the two databases.
2880410302eSdanielk1977  #
2893d0cbc33Sdanielk1977  execsql { PRAGMA page_size = 1024 }
2903d0cbc33Sdanielk1977  execsql "PRAGMA page_size = $nDestPgsz" db2
2913d0cbc33Sdanielk1977  foreach db {db db2} {
2920410302eSdanielk1977    execsql {
2930410302eSdanielk1977      BEGIN;
2940410302eSdanielk1977      CREATE TABLE t1(a, b);
2950410302eSdanielk1977      CREATE INDEX i1 ON t1(a, b);
2963d0cbc33Sdanielk1977      COMMIT;
2970410302eSdanielk1977    } $db
2980410302eSdanielk1977  }
2993d0cbc33Sdanielk1977  while {[file size test.db]/1024 < $nSrcPg} {
3003d0cbc33Sdanielk1977    execsql { INSERT INTO t1 VALUES($ii, randstr(200,200)) }
3013d0cbc33Sdanielk1977  }
3023d0cbc33Sdanielk1977
3033d0cbc33Sdanielk1977  for {set ii 0} {$ii < $nDestRow} {incr ii} {
3043d0cbc33Sdanielk1977    execsql { INSERT INTO t1 VALUES($ii, randstr(1000,1000)) } db2
3050410302eSdanielk1977  }
3060410302eSdanielk1977
3070410302eSdanielk1977  # Backup the source database.
3080410302eSdanielk1977  do_test backup-3.$iTest.1 {
3090410302eSdanielk1977    sqlite3_backup B db main db2 main
3100410302eSdanielk1977    while {[B step 10]=="SQLITE_OK"} {}
3110410302eSdanielk1977    B finish
3120410302eSdanielk1977  } {SQLITE_OK}
3130410302eSdanielk1977
3140410302eSdanielk1977  # Run integrity check on the backup.
3150410302eSdanielk1977  do_test backup-3.$iTest.2 {
3160410302eSdanielk1977    execsql "PRAGMA integrity_check" db2
3170410302eSdanielk1977  } {ok}
3180410302eSdanielk1977
3190410302eSdanielk1977  test_contents backup-3.$iTest.3 db main db2 main
3200410302eSdanielk1977
3210410302eSdanielk1977  db close
3220410302eSdanielk1977  db2 close
3230410302eSdanielk1977  incr iTest
3240410302eSdanielk1977}
3250410302eSdanielk1977}
3260410302eSdanielk1977}
327f2a79f22Sdanielk1977
328f2a79f22Sdanielk1977#--------------------------------------------------------------------
329f2a79f22Sdanielk1977do_test backup-3.$iTest.1 {
330fda06befSmistachkin  catch { forcedelete test.db }
331fda06befSmistachkin  catch { forcedelete test2.db }
332f2a79f22Sdanielk1977  sqlite3 db test.db
333f2a79f22Sdanielk1977  set iTab 1
334f2a79f22Sdanielk1977
335f2a79f22Sdanielk1977  db eval { PRAGMA page_size = 512 }
336f2a79f22Sdanielk1977  while {[file size test.db] <= $::sqlite_pending_byte} {
337f2a79f22Sdanielk1977    db eval "CREATE TABLE t${iTab}(a, b, c)"
338f2a79f22Sdanielk1977    incr iTab
339f2a79f22Sdanielk1977  }
340f2a79f22Sdanielk1977
341f2a79f22Sdanielk1977  sqlite3 db2 test2.db
342f2a79f22Sdanielk1977  db2 eval { PRAGMA page_size = 4096 }
343f2a79f22Sdanielk1977  while {[file size test2.db] < $::sqlite_pending_byte} {
344f2a79f22Sdanielk1977    db2 eval "CREATE TABLE t${iTab}(a, b, c)"
345f2a79f22Sdanielk1977    incr iTab
346f2a79f22Sdanielk1977  }
347f2a79f22Sdanielk1977
348f2a79f22Sdanielk1977  sqlite3_backup B db2 main db main
349f2a79f22Sdanielk1977  B step -1
350f2a79f22Sdanielk1977} {SQLITE_DONE}
351f2a79f22Sdanielk1977
352f2a79f22Sdanielk1977do_test backup-3.$iTest.2 {
353f2a79f22Sdanielk1977  B finish
354f2a79f22Sdanielk1977} {SQLITE_OK}
355f2a79f22Sdanielk1977
3560410302eSdanielk1977#
3570410302eSdanielk1977# End of backup-3.* tests.
3580410302eSdanielk1977#---------------------------------------------------------------------
3590410302eSdanielk1977
3600410302eSdanielk1977
3610410302eSdanielk1977#---------------------------------------------------------------------
3620410302eSdanielk1977# The following tests, backup-4.*, test various error conditions:
3630410302eSdanielk1977#
3640410302eSdanielk1977# backup-4.1.*: Test invalid database names.
3650410302eSdanielk1977#
3660410302eSdanielk1977# backup-4.2.*: Test that the source database cannot be detached while
3670410302eSdanielk1977#               a backup is in progress.
3680410302eSdanielk1977#
3690410302eSdanielk1977# backup-4.3.*: Test that the source database handle cannot be closed
3700410302eSdanielk1977#               while a backup is in progress.
3710410302eSdanielk1977#
3720410302eSdanielk1977# backup-4.4.*: Test an attempt to specify the same handle for the
3730410302eSdanielk1977#               source and destination databases.
3740410302eSdanielk1977#
3750410302eSdanielk1977# backup-4.5.*: Test that an in-memory destination with a different
3760410302eSdanielk1977#               page-size to the source database is an error.
3770410302eSdanielk1977#
3780410302eSdanielk1977sqlite3 db test.db
3790410302eSdanielk1977sqlite3 db2 test2.db
3800410302eSdanielk1977
3810410302eSdanielk1977do_test backup-4.1.1 {
3820410302eSdanielk1977  catch { sqlite3_backup B db aux db2 main }
3830410302eSdanielk1977} {1}
3840410302eSdanielk1977do_test backup-4.1.2 {
3850410302eSdanielk1977  sqlite3_errmsg db
3860410302eSdanielk1977} {unknown database aux}
3870410302eSdanielk1977do_test backup-4.1.3 {
3880410302eSdanielk1977  catch { sqlite3_backup B db main db2 aux }
3890410302eSdanielk1977} {1}
3900410302eSdanielk1977do_test backup-4.1.4 {
3910410302eSdanielk1977  sqlite3_errmsg db
3920410302eSdanielk1977} {unknown database aux}
3930410302eSdanielk1977
3940410302eSdanielk1977do_test backup-4.2.1 {
395fda06befSmistachkin  catch { forcedelete test3.db }
396fda06befSmistachkin  catch { forcedelete test4.db }
3973d781c21Sdanielk1977  execsql {
3983d781c21Sdanielk1977    ATTACH 'test3.db' AS aux1;
3993d781c21Sdanielk1977    CREATE TABLE aux1.t1(a, b);
4003d781c21Sdanielk1977  }
4013d781c21Sdanielk1977  execsql {
4023d781c21Sdanielk1977    ATTACH 'test4.db' AS aux2;
4033d781c21Sdanielk1977    CREATE TABLE aux2.t2(a, b);
4043d781c21Sdanielk1977  } db2
4050410302eSdanielk1977  sqlite3_backup B db aux1 db2 aux2
4060410302eSdanielk1977} {B}
4070410302eSdanielk1977do_test backup-4.2.2 {
4080410302eSdanielk1977  catchsql { DETACH aux2 } db2
4090410302eSdanielk1977} {1 {database aux2 is locked}}
4100410302eSdanielk1977do_test backup-4.2.3 {
4110410302eSdanielk1977  B step 50
4120410302eSdanielk1977} {SQLITE_DONE}
4130410302eSdanielk1977do_test backup-4.2.4 {
4140410302eSdanielk1977  B finish
4150410302eSdanielk1977} {SQLITE_OK}
4160410302eSdanielk1977
4170410302eSdanielk1977do_test backup-4.3.1 {
4180410302eSdanielk1977  sqlite3_backup B db aux1 db2 aux2
4190410302eSdanielk1977} {B}
4200410302eSdanielk1977do_test backup-4.3.2 {
4210410302eSdanielk1977  db2 cache flush
422167cd6abSdrh  sqlite3_close db2
423167cd6abSdrh} {SQLITE_BUSY}
424167cd6abSdrhdo_test backup-4.3.3 {
425167cd6abSdrh  sqlite3_errmsg db2
426167cd6abSdrh} {unable to close due to unfinalized statements or unfinished backups}
4270410302eSdanielk1977do_test backup-4.3.4 {
4280410302eSdanielk1977  B step 50
4290410302eSdanielk1977} {SQLITE_DONE}
4300410302eSdanielk1977do_test backup-4.3.5 {
4310410302eSdanielk1977  B finish
4320410302eSdanielk1977} {SQLITE_OK}
4330410302eSdanielk1977
4340410302eSdanielk1977do_test backup-4.4.1 {
4350410302eSdanielk1977  set rc [catch {sqlite3_backup B db main db aux1}]
4360410302eSdanielk1977  list $rc [sqlite3_errcode db] [sqlite3_errmsg db]
437b309becdSdrh} {1 SQLITE_ERROR {source and destination must be distinct}}
4380410302eSdanielk1977db close
439167cd6abSdrhdb2 close
4400410302eSdanielk1977
4410410302eSdanielk1977do_test backup-4.5.1 {
442fda06befSmistachkin  catch { forcedelete test.db }
4430410302eSdanielk1977  sqlite3 db test.db
4440410302eSdanielk1977  sqlite3 db2 :memory:
4450410302eSdanielk1977  execsql {
4460410302eSdanielk1977    CREATE TABLE t1(a, b);
4470410302eSdanielk1977    INSERT INTO t1 VALUES(1, 2);
4480410302eSdanielk1977  }
4490410302eSdanielk1977  execsql {
4500410302eSdanielk1977    PRAGMA page_size = 4096;
4510410302eSdanielk1977    CREATE TABLE t2(a, b);
4520410302eSdanielk1977    INSERT INTO t2 VALUES(3, 4);
4530410302eSdanielk1977  } db2
4540410302eSdanielk1977  sqlite3_backup B db2 main db main
4550410302eSdanielk1977} {B}
4560410302eSdanielk1977do_test backup-4.5.2 {
4570410302eSdanielk1977  B step 5000
4580410302eSdanielk1977} {SQLITE_READONLY}
4590410302eSdanielk1977do_test backup-4.5.3 {
4600410302eSdanielk1977  B finish
4610410302eSdanielk1977} {SQLITE_READONLY}
4620410302eSdanielk1977
4630410302eSdanielk1977db close
4640410302eSdanielk1977db2 close
4650410302eSdanielk1977#
4661feff7f1Sdan# End of backup-4.* tests.
4670410302eSdanielk1977#---------------------------------------------------------------------
4680410302eSdanielk1977
4690410302eSdanielk1977#---------------------------------------------------------------------
4700410302eSdanielk1977# The following tests, backup-5.*, test that the backup works properly
4710410302eSdanielk1977# when the source database is modified during the backup. Test cases
4720410302eSdanielk1977# are organized as follows:
4730410302eSdanielk1977#
4740410302eSdanielk1977# backup-5.x.1.*: Nothing special. Modify the database mid-backup.
4750410302eSdanielk1977#
4760410302eSdanielk1977# backup-5.x.2.*: Modify the database mid-backup so that one or more
4770410302eSdanielk1977#                 pages are written out due to cache stress. Then
4780410302eSdanielk1977#                 rollback the transaction.
4790410302eSdanielk1977#
4800410302eSdanielk1977# backup-5.x.3.*: Database is vacuumed.
4810410302eSdanielk1977#
4820410302eSdanielk1977# backup-5.x.4.*: Database is vacuumed and the page-size modified.
4830410302eSdanielk1977#
4840410302eSdanielk1977# backup-5.x.5.*: Database is shrunk via incr-vacuum.
4850410302eSdanielk1977#
4860410302eSdanielk1977# Each test is run three times, in the following configurations:
4870410302eSdanielk1977#
4880410302eSdanielk1977#   1) Backing up file-to-file. The writer writes via an external pager.
4890410302eSdanielk1977#   2) Backing up file-to-file. The writer writes via the same pager as
4900410302eSdanielk1977#      is used by the backup operation.
4910410302eSdanielk1977#   3) Backing up memory-to-file.
4920410302eSdanielk1977#
4930410302eSdanielk1977set iTest 0
494fda06befSmistachkinforcedelete bak.db-wal
4950410302eSdanielk1977foreach {writer file} {db test.db db3 test.db db :memory:} {
4960410302eSdanielk1977  incr iTest
497fda06befSmistachkin  catch { delete_file bak.db }
4980410302eSdanielk1977  sqlite3 db2 bak.db
499fda06befSmistachkin  catch { delete_file $file }
5000410302eSdanielk1977  sqlite3 db $file
5010410302eSdanielk1977  sqlite3 db3 $file
5020410302eSdanielk1977
5030410302eSdanielk1977  do_test backup-5.$iTest.1.1 {
5040410302eSdanielk1977    execsql {
5050410302eSdanielk1977      BEGIN;
5060410302eSdanielk1977      CREATE TABLE t1(a, b);
5070410302eSdanielk1977      CREATE INDEX i1 ON t1(a, b);
5080410302eSdanielk1977      INSERT INTO t1 VALUES(1, randstr(1000,1000));
5090410302eSdanielk1977      INSERT INTO t1 VALUES(2, randstr(1000,1000));
5100410302eSdanielk1977      INSERT INTO t1 VALUES(3, randstr(1000,1000));
5110410302eSdanielk1977      INSERT INTO t1 VALUES(4, randstr(1000,1000));
5120410302eSdanielk1977      INSERT INTO t1 VALUES(5, randstr(1000,1000));
5130410302eSdanielk1977      COMMIT;
5140410302eSdanielk1977    }
5150410302eSdanielk1977    expr {[execsql {PRAGMA page_count}] > 10}
5160410302eSdanielk1977  } {1}
5170410302eSdanielk1977  do_test backup-5.$iTest.1.2 {
5180410302eSdanielk1977    sqlite3_backup B db2 main db main
5190410302eSdanielk1977    B step 5
5200410302eSdanielk1977  } {SQLITE_OK}
5210410302eSdanielk1977  do_test backup-5.$iTest.1.3 {
5220410302eSdanielk1977    execsql { UPDATE t1 SET a = a + 1 } $writer
5230410302eSdanielk1977    B step 50
5240410302eSdanielk1977  } {SQLITE_DONE}
5250410302eSdanielk1977  do_test backup-5.$iTest.1.4 {
5260410302eSdanielk1977    B finish
5270410302eSdanielk1977  } {SQLITE_OK}
5280410302eSdanielk1977  integrity_check backup-5.$iTest.1.5 db2
5290410302eSdanielk1977  test_contents backup-5.$iTest.1.6 db main db2 main
5300410302eSdanielk1977
5310410302eSdanielk1977  do_test backup-5.$iTest.2.1 {
5320410302eSdanielk1977    execsql {
5330410302eSdanielk1977      PRAGMA cache_size = 10;
5340410302eSdanielk1977      BEGIN;
5350410302eSdanielk1977      INSERT INTO t1 SELECT '', randstr(1000,1000) FROM t1;
5360410302eSdanielk1977      INSERT INTO t1 SELECT '', randstr(1000,1000) FROM t1;
5370410302eSdanielk1977      INSERT INTO t1 SELECT '', randstr(1000,1000) FROM t1;
5380410302eSdanielk1977      INSERT INTO t1 SELECT '', randstr(1000,1000) FROM t1;
5390410302eSdanielk1977      COMMIT;
5400410302eSdanielk1977    }
5410410302eSdanielk1977  } {}
5420410302eSdanielk1977  do_test backup-5.$iTest.2.2 {
5430410302eSdanielk1977    sqlite3_backup B db2 main db main
5440410302eSdanielk1977    B step 50
5450410302eSdanielk1977  } {SQLITE_OK}
5460410302eSdanielk1977  do_test backup-5.$iTest.2.3 {
5470410302eSdanielk1977    execsql {
5480410302eSdanielk1977      BEGIN;
5490410302eSdanielk1977      UPDATE t1 SET a = a + 1;
5500410302eSdanielk1977      ROLLBACK;
5510410302eSdanielk1977    } $writer
5520410302eSdanielk1977    B step 5000
5530410302eSdanielk1977  } {SQLITE_DONE}
5540410302eSdanielk1977  do_test backup-5.$iTest.2.4 {
5550410302eSdanielk1977    B finish
5560410302eSdanielk1977  } {SQLITE_OK}
5570410302eSdanielk1977  integrity_check backup-5.$iTest.2.5 db2
5580410302eSdanielk1977  test_contents backup-5.$iTest.2.6 db main db2 main
5590410302eSdanielk1977
5600410302eSdanielk1977  do_test backup-5.$iTest.3.1 {
5610410302eSdanielk1977    execsql { UPDATE t1 SET b = randstr(1000,1000) }
5620410302eSdanielk1977  } {}
5630410302eSdanielk1977  do_test backup-5.$iTest.3.2 {
5640410302eSdanielk1977    sqlite3_backup B db2 main db main
5650410302eSdanielk1977    B step 50
5660410302eSdanielk1977  } {SQLITE_OK}
5670410302eSdanielk1977  do_test backup-5.$iTest.3.3 {
5680410302eSdanielk1977    execsql { VACUUM } $writer
5690410302eSdanielk1977    B step 5000
5700410302eSdanielk1977  } {SQLITE_DONE}
5710410302eSdanielk1977  do_test backup-5.$iTest.3.4 {
5720410302eSdanielk1977    B finish
5730410302eSdanielk1977  } {SQLITE_OK}
5740410302eSdanielk1977  integrity_check backup-5.$iTest.3.5 db2
5750410302eSdanielk1977  test_contents backup-5.$iTest.3.6 db main db2 main
5760410302eSdanielk1977
5770410302eSdanielk1977  do_test backup-5.$iTest.4.1 {
5780410302eSdanielk1977    execsql { UPDATE t1 SET b = randstr(1000,1000) }
5790410302eSdanielk1977  } {}
5800410302eSdanielk1977  do_test backup-5.$iTest.4.2 {
5810410302eSdanielk1977    sqlite3_backup B db2 main db main
5820410302eSdanielk1977    B step 50
5830410302eSdanielk1977  } {SQLITE_OK}
5840410302eSdanielk1977  do_test backup-5.$iTest.4.3 {
5850410302eSdanielk1977    execsql {
5860410302eSdanielk1977      PRAGMA page_size = 2048;
5870410302eSdanielk1977      VACUUM;
5880410302eSdanielk1977    } $writer
5890410302eSdanielk1977    B step 5000
5900410302eSdanielk1977  } {SQLITE_DONE}
5910410302eSdanielk1977  do_test backup-5.$iTest.4.4 {
5920410302eSdanielk1977    B finish
5930410302eSdanielk1977  } {SQLITE_OK}
5940410302eSdanielk1977  integrity_check backup-5.$iTest.4.5 db2
5950410302eSdanielk1977  test_contents backup-5.$iTest.4.6 db main db2 main
5960410302eSdanielk1977
597ce14f624Sshane  catch {db close}
598ce14f624Sshane  catch {db2 close}
599ce14f624Sshane  catch {db3 close}
600fda06befSmistachkin  catch { delete_file bak.db }
6010410302eSdanielk1977  sqlite3 db2 bak.db
602fda06befSmistachkin  catch { delete_file $file }
6030410302eSdanielk1977  sqlite3 db $file
6040410302eSdanielk1977  sqlite3 db3 $file
6050410302eSdanielk1977  do_test backup-5.$iTest.5.1 {
6060410302eSdanielk1977    execsql {
6070410302eSdanielk1977      PRAGMA auto_vacuum = incremental;
6080410302eSdanielk1977      BEGIN;
6090410302eSdanielk1977      CREATE TABLE t1(a, b);
6100410302eSdanielk1977      CREATE INDEX i1 ON t1(a, b);
6110410302eSdanielk1977      INSERT INTO t1 VALUES(1, randstr(1000,1000));
6120410302eSdanielk1977      INSERT INTO t1 VALUES(2, randstr(1000,1000));
6130410302eSdanielk1977      INSERT INTO t1 VALUES(3, randstr(1000,1000));
6140410302eSdanielk1977      INSERT INTO t1 VALUES(4, randstr(1000,1000));
6150410302eSdanielk1977      INSERT INTO t1 VALUES(5, randstr(1000,1000));
6160410302eSdanielk1977      COMMIT;
6170410302eSdanielk1977    }
6180410302eSdanielk1977  } {}
6190410302eSdanielk1977  do_test backup-5.$iTest.5.2 {
6200410302eSdanielk1977    sqlite3_backup B db2 main db main
6210410302eSdanielk1977    B step 8
6220410302eSdanielk1977  } {SQLITE_OK}
6230410302eSdanielk1977  do_test backup-5.$iTest.5.3 {
6240410302eSdanielk1977    execsql {
6250410302eSdanielk1977      DELETE FROM t1;
6260410302eSdanielk1977      PRAGMA incremental_vacuum;
6270410302eSdanielk1977    } $writer
6280410302eSdanielk1977    B step 50
6290410302eSdanielk1977  } {SQLITE_DONE}
6300410302eSdanielk1977  do_test backup-5.$iTest.5.4 {
6310410302eSdanielk1977    B finish
6320410302eSdanielk1977  } {SQLITE_OK}
6330410302eSdanielk1977  integrity_check backup-5.$iTest.5.5 db2
6340410302eSdanielk1977  test_contents backup-5.$iTest.5.6 db main db2 main
6350410302eSdanielk1977  catch {db close}
6360410302eSdanielk1977  catch {db2 close}
6370410302eSdanielk1977  catch {db3 close}
638ce14f624Sshane}
6390410302eSdanielk1977#
6400410302eSdanielk1977# End of backup-5.* tests.
6410410302eSdanielk1977#---------------------------------------------------------------------
6420410302eSdanielk1977
6430410302eSdanielk1977#---------------------------------------------------------------------
6440410302eSdanielk1977# Test the sqlite3_backup_remaining() and backup_pagecount() APIs.
6450410302eSdanielk1977#
6460410302eSdanielk1977do_test backup-6.1 {
647fda06befSmistachkin  catch { forcedelete test.db }
648fda06befSmistachkin  catch { forcedelete test2.db }
6490410302eSdanielk1977  sqlite3 db test.db
6500410302eSdanielk1977  sqlite3 db2 test2.db
6510410302eSdanielk1977  execsql {
6520410302eSdanielk1977    BEGIN;
6530410302eSdanielk1977    CREATE TABLE t1(a, b);
6540410302eSdanielk1977    CREATE INDEX i1 ON t1(a, b);
6550410302eSdanielk1977    INSERT INTO t1 VALUES(1, randstr(1000,1000));
6560410302eSdanielk1977    INSERT INTO t1 VALUES(2, randstr(1000,1000));
6570410302eSdanielk1977    INSERT INTO t1 VALUES(3, randstr(1000,1000));
6580410302eSdanielk1977    INSERT INTO t1 VALUES(4, randstr(1000,1000));
6590410302eSdanielk1977    INSERT INTO t1 VALUES(5, randstr(1000,1000));
6600410302eSdanielk1977    COMMIT;
6610410302eSdanielk1977  }
6620410302eSdanielk1977} {}
6630410302eSdanielk1977do_test backup-6.2 {
6640410302eSdanielk1977  set nTotal [expr {[file size test.db]/1024}]
6650410302eSdanielk1977  sqlite3_backup B db2 main db main
6660410302eSdanielk1977  B step 1
6670410302eSdanielk1977} {SQLITE_OK}
6680410302eSdanielk1977do_test backup-6.3 {
6690410302eSdanielk1977  B pagecount
6700410302eSdanielk1977} $nTotal
6710410302eSdanielk1977do_test backup-6.4 {
6720410302eSdanielk1977  B remaining
6730410302eSdanielk1977} [expr $nTotal-1]
6740410302eSdanielk1977do_test backup-6.5 {
6750410302eSdanielk1977  B step 5
6760410302eSdanielk1977  list [B remaining] [B pagecount]
6770410302eSdanielk1977} [list [expr $nTotal-6] $nTotal]
6780410302eSdanielk1977do_test backup-6.6 {
6790410302eSdanielk1977  execsql { CREATE TABLE t2(a PRIMARY KEY, b) }
6800410302eSdanielk1977  B step 1
6810410302eSdanielk1977  list [B remaining] [B pagecount]
6820410302eSdanielk1977} [list [expr $nTotal-5] [expr $nTotal+2]]
6830410302eSdanielk1977
6840410302eSdanielk1977do_test backup-6.X {
6850410302eSdanielk1977  B finish
6860410302eSdanielk1977} {SQLITE_OK}
6870410302eSdanielk1977
688ce14f624Sshanecatch {db close}
689ce14f624Sshanecatch {db2 close}
6900410302eSdanielk1977
6910410302eSdanielk1977#---------------------------------------------------------------------
6920410302eSdanielk1977# Test cases backup-7.* test that SQLITE_BUSY and SQLITE_LOCKED errors
6930410302eSdanielk1977# are returned correctly:
6940410302eSdanielk1977#
6950410302eSdanielk1977# backup-7.1.*: Source database is externally locked (return SQLITE_BUSY).
6960410302eSdanielk1977#
6970410302eSdanielk1977# backup-7.2.*: Attempt to step the backup process while a
6980410302eSdanielk1977#               write-transaction is underway on the source pager (return
6990410302eSdanielk1977#               SQLITE_LOCKED).
7000410302eSdanielk1977#
7010410302eSdanielk1977# backup-7.3.*: Destination database is externally locked (return SQLITE_BUSY).
7020410302eSdanielk1977#
7030410302eSdanielk1977do_test backup-7.0 {
704fda06befSmistachkin  catch { forcedelete test.db }
705fda06befSmistachkin  catch { forcedelete test2.db }
7060410302eSdanielk1977  sqlite3 db2 test2.db
7070410302eSdanielk1977  sqlite3 db test.db
7080410302eSdanielk1977  execsql {
7090410302eSdanielk1977    CREATE TABLE t1(a, b);
7100410302eSdanielk1977    CREATE INDEX i1 ON t1(a, b);
7110410302eSdanielk1977    INSERT INTO t1 VALUES(1, randstr(1000,1000));
7120410302eSdanielk1977    INSERT INTO t1 SELECT a+ 1, randstr(1000,1000) FROM t1;
7130410302eSdanielk1977    INSERT INTO t1 SELECT a+ 2, randstr(1000,1000) FROM t1;
7140410302eSdanielk1977    INSERT INTO t1 SELECT a+ 4, randstr(1000,1000) FROM t1;
7150410302eSdanielk1977    INSERT INTO t1 SELECT a+ 8, randstr(1000,1000) FROM t1;
7160410302eSdanielk1977    INSERT INTO t1 SELECT a+16, randstr(1000,1000) FROM t1;
7170410302eSdanielk1977    INSERT INTO t1 SELECT a+32, randstr(1000,1000) FROM t1;
7180410302eSdanielk1977    INSERT INTO t1 SELECT a+64, randstr(1000,1000) FROM t1;
7190410302eSdanielk1977  }
7200410302eSdanielk1977} {}
7210410302eSdanielk1977
7220410302eSdanielk1977do_test backup-7.1.1 {
7230410302eSdanielk1977  sqlite3_backup B db2 main db main
7240410302eSdanielk1977  B step 5
7250410302eSdanielk1977} {SQLITE_OK}
7260410302eSdanielk1977do_test backup-7.1.2 {
7270410302eSdanielk1977  sqlite3 db3 test.db
7280410302eSdanielk1977  execsql { BEGIN EXCLUSIVE } db3
7290410302eSdanielk1977  B step 5
7300410302eSdanielk1977} {SQLITE_BUSY}
7310410302eSdanielk1977do_test backup-7.1.3 {
7320410302eSdanielk1977  execsql { ROLLBACK } db3
7330410302eSdanielk1977  B step 5
7340410302eSdanielk1977} {SQLITE_OK}
7350410302eSdanielk1977do_test backup-7.2.1 {
7360410302eSdanielk1977  execsql {
7370410302eSdanielk1977    BEGIN;
7380410302eSdanielk1977    INSERT INTO t1 VALUES(1, 4);
7390410302eSdanielk1977  }
7400410302eSdanielk1977} {}
7410410302eSdanielk1977do_test backup-7.2.2 {
7420410302eSdanielk1977  B step 5000
743404ca075Sdanielk1977} {SQLITE_BUSY}
7440410302eSdanielk1977do_test backup-7.2.3 {
7450410302eSdanielk1977  execsql { ROLLBACK }
7460410302eSdanielk1977  B step 5000
7470410302eSdanielk1977} {SQLITE_DONE}
7480410302eSdanielk1977do_test backup-7.2.4 {
7490410302eSdanielk1977  B finish
7500410302eSdanielk1977} {SQLITE_OK}
7510410302eSdanielk1977test_contents backup-7.2.5 db main db2 main
7520410302eSdanielk1977integrity_check backup-7.3.6 db2
7530410302eSdanielk1977
7540410302eSdanielk1977do_test backup-7.3.1 {
7550410302eSdanielk1977  db2 close
7560410302eSdanielk1977  db3 close
757fda06befSmistachkin  forcedelete test2.db
7580410302eSdanielk1977  sqlite3 db2 test2.db
7590410302eSdanielk1977  sqlite3 db3 test2.db
7600410302eSdanielk1977
7610410302eSdanielk1977  sqlite3_backup B db2 main db main
7620410302eSdanielk1977  execsql { BEGIN ; CREATE TABLE t2(a, b); } db3
7630410302eSdanielk1977
7640410302eSdanielk1977  B step 5
7650410302eSdanielk1977} {SQLITE_BUSY}
7660410302eSdanielk1977do_test backup-7.3.2 {
7670410302eSdanielk1977  execsql { COMMIT } db3
7680410302eSdanielk1977  B step 5000
7690410302eSdanielk1977} {SQLITE_DONE}
7700410302eSdanielk1977do_test backup-7.3.3 {
7710410302eSdanielk1977  B finish
7720410302eSdanielk1977} {SQLITE_OK}
7730410302eSdanielk1977test_contents backup-7.3.4 db main db2 main
7740410302eSdanielk1977integrity_check backup-7.3.5 db2
7750410302eSdanielk1977catch { db2 close }
7760410302eSdanielk1977catch { db3 close }
7770410302eSdanielk1977
7780410302eSdanielk1977#-----------------------------------------------------------------------
7790410302eSdanielk1977# The following tests, backup-8.*, test attaching multiple backup
7800410302eSdanielk1977# processes to the same source database. Also, reading from the source
7810410302eSdanielk1977# database while a read transaction is active.
7820410302eSdanielk1977#
7830410302eSdanielk1977# These tests reuse the database "test.db" left over from backup-7.*.
7840410302eSdanielk1977#
7850410302eSdanielk1977do_test backup-8.1 {
786fda06befSmistachkin  catch { forcedelete test2.db }
787fda06befSmistachkin  catch { forcedelete test3.db }
7880410302eSdanielk1977  sqlite3 db2 test2.db
7890410302eSdanielk1977  sqlite3 db3 test3.db
7900410302eSdanielk1977
7910410302eSdanielk1977  sqlite3_backup B2 db2 main db main
7920410302eSdanielk1977  sqlite3_backup B3 db3 main db main
7930410302eSdanielk1977  list [B2 finish] [B3 finish]
7940410302eSdanielk1977} {SQLITE_OK SQLITE_OK}
7950410302eSdanielk1977do_test backup-8.2 {
7960410302eSdanielk1977  sqlite3_backup B3 db3 main db main
7970410302eSdanielk1977  sqlite3_backup B2 db2 main db main
7980410302eSdanielk1977  list [B2 finish] [B3 finish]
7990410302eSdanielk1977} {SQLITE_OK SQLITE_OK}
8000410302eSdanielk1977do_test backup-8.3 {
8010410302eSdanielk1977  sqlite3_backup B2 db2 main db main
8020410302eSdanielk1977  sqlite3_backup B3 db3 main db main
8030410302eSdanielk1977  B2 step 5
8040410302eSdanielk1977} {SQLITE_OK}
8050410302eSdanielk1977do_test backup-8.4 {
8060410302eSdanielk1977  execsql {
8070410302eSdanielk1977    BEGIN;
8080410302eSdanielk1977    SELECT * FROM sqlite_master;
8090410302eSdanielk1977  }
8100410302eSdanielk1977  B3 step 5
8110410302eSdanielk1977} {SQLITE_OK}
8120410302eSdanielk1977do_test backup-8.5 {
8130410302eSdanielk1977  list [B3 step 5000] [B3 finish]
8140410302eSdanielk1977} {SQLITE_DONE SQLITE_OK}
8150410302eSdanielk1977do_test backup-8.6 {
8160410302eSdanielk1977  list [B2 step 5000] [B2 finish]
8170410302eSdanielk1977} {SQLITE_DONE SQLITE_OK}
8180410302eSdanielk1977test_contents backup-8.7 db main db2 main
8190410302eSdanielk1977test_contents backup-8.8 db main db3 main
8200410302eSdanielk1977do_test backup-8.9 {
8210410302eSdanielk1977  execsql { PRAGMA lock_status }
8220410302eSdanielk1977} {main shared temp closed}
8230410302eSdanielk1977do_test backup-8.10 {
8240410302eSdanielk1977  execsql COMMIT
8250410302eSdanielk1977} {}
8260410302eSdanielk1977catch { db2 close }
8270410302eSdanielk1977catch { db3 close }
8280410302eSdanielk1977
82903ab0357Sdanielk1977#-----------------------------------------------------------------------
83003ab0357Sdanielk1977# The following tests, backup-9.*, test that:
83103ab0357Sdanielk1977#
83203ab0357Sdanielk1977#   * Passing 0 as an argument to sqlite3_backup_step() means no pages
83303ab0357Sdanielk1977#     are backed up (backup-9.1.*), and
83403ab0357Sdanielk1977#   * Passing a negative value as an argument to sqlite3_backup_step() means
83503ab0357Sdanielk1977#     all pages are backed up (backup-9.2.*).
83603ab0357Sdanielk1977#
83703ab0357Sdanielk1977# These tests reuse the database "test.db" left over from backup-7.*.
83803ab0357Sdanielk1977#
83903ab0357Sdanielk1977do_test backup-9.1.1 {
84003ab0357Sdanielk1977  sqlite3 db2 test2.db
84103ab0357Sdanielk1977  sqlite3_backup B db2 main db main
84203ab0357Sdanielk1977  B step 1
84303ab0357Sdanielk1977} {SQLITE_OK}
84403ab0357Sdanielk1977do_test backup-9.1.2 {
84503ab0357Sdanielk1977  set nRemaining [B remaining]
84603ab0357Sdanielk1977  expr {$nRemaining>100}
84703ab0357Sdanielk1977} {1}
84803ab0357Sdanielk1977do_test backup-9.1.3 {
84903ab0357Sdanielk1977  B step 0
85003ab0357Sdanielk1977} {SQLITE_OK}
85103ab0357Sdanielk1977do_test backup-9.1.4 {
85203ab0357Sdanielk1977  B remaining
85303ab0357Sdanielk1977} $nRemaining
85403ab0357Sdanielk1977
85503ab0357Sdanielk1977do_test backup-9.2.1 {
85603ab0357Sdanielk1977  B step -1
85703ab0357Sdanielk1977} {SQLITE_DONE}
85803ab0357Sdanielk1977do_test backup-9.2.2 {
85903ab0357Sdanielk1977  B remaining
86003ab0357Sdanielk1977} {0}
86103ab0357Sdanielk1977do_test backup-9.2.3 {
86203ab0357Sdanielk1977  B finish
86303ab0357Sdanielk1977} {SQLITE_OK}
86403ab0357Sdanielk1977catch {db2 close}
8650410302eSdanielk1977
866e70f4f64Sdanielk1977ifcapable memorymanage {
867e70f4f64Sdanielk1977  db close
868fda06befSmistachkin  forcedelete test.db
869fda06befSmistachkin  forcedelete bak.db
870e70f4f64Sdanielk1977
871e70f4f64Sdanielk1977  sqlite3 db test.db
872e70f4f64Sdanielk1977  sqlite3 db2 test.db
873e70f4f64Sdanielk1977  sqlite3 db3 bak.db
874e70f4f64Sdanielk1977
875e70f4f64Sdanielk1977  do_test backup-10.1.1 {
876e70f4f64Sdanielk1977    execsql {
877e70f4f64Sdanielk1977      BEGIN;
878e70f4f64Sdanielk1977      CREATE TABLE t1(a, b);
879e70f4f64Sdanielk1977      INSERT INTO t1 VALUES(1, randstr(1000,1000));
880e70f4f64Sdanielk1977      INSERT INTO t1 VALUES(2, randstr(1000,1000));
881e70f4f64Sdanielk1977      INSERT INTO t1 VALUES(3, randstr(1000,1000));
882e70f4f64Sdanielk1977      INSERT INTO t1 VALUES(4, randstr(1000,1000));
883e70f4f64Sdanielk1977      INSERT INTO t1 VALUES(5, randstr(1000,1000));
884e70f4f64Sdanielk1977      CREATE INDEX i1 ON t1(a, b);
885e70f4f64Sdanielk1977      COMMIT;
886e70f4f64Sdanielk1977    }
887e70f4f64Sdanielk1977  } {}
888e70f4f64Sdanielk1977  do_test backup-10.1.2 {
889e70f4f64Sdanielk1977    sqlite3_backup B db3 main db2 main
890e70f4f64Sdanielk1977    B step 5
891e70f4f64Sdanielk1977  } {SQLITE_OK}
892e70f4f64Sdanielk1977  do_test backup-10.1.3 {
893e70f4f64Sdanielk1977    execsql {
894e70f4f64Sdanielk1977      UPDATE t1 SET b = randstr(500,500);
895e70f4f64Sdanielk1977    }
896e70f4f64Sdanielk1977  } {}
897e70f4f64Sdanielk1977  sqlite3_release_memory [expr 1024*1024]
898e70f4f64Sdanielk1977  do_test backup-10.1.3 {
899e70f4f64Sdanielk1977    B step 50
900e70f4f64Sdanielk1977  } {SQLITE_DONE}
901e70f4f64Sdanielk1977  do_test backup-10.1.4 {
902e70f4f64Sdanielk1977    B finish
903e70f4f64Sdanielk1977  } {SQLITE_OK}
904e70f4f64Sdanielk1977  do_test backup-10.1.5 {
905e70f4f64Sdanielk1977    execsql { PRAGMA integrity_check } db3
906e70f4f64Sdanielk1977  } {ok}
907e70f4f64Sdanielk1977
908e70f4f64Sdanielk1977  db2 close
909e70f4f64Sdanielk1977  db3 close
910e70f4f64Sdanielk1977}
911e70f4f64Sdanielk1977
91233d58bceSdan
9133306c4a9Sdan#-----------------------------------------------------------------------
91433d58bceSdan# Test that if the database is written to via the same database handle being
91533d58bceSdan# used as the source by a backup operation:
91633d58bceSdan#
91733d58bceSdan#   10.1.*: If the db is in-memory, the backup is restarted.
91833d58bceSdan#   10.2.*: If the db is a file, the backup is not restarted.
91933d58bceSdan#
92033d58bceSdandb close
921fda06befSmistachkinforcedelete test.db test.db-journal
92233d58bceSdanforeach {tn file rc} {
92333d58bceSdan  1 test.db  SQLITE_DONE
92433d58bceSdan  2 :memory: SQLITE_OK
92533d58bceSdan} {
92633d58bceSdan  do_test backup-10.$tn.1 {
92733d58bceSdan    sqlite3 db $file
92833d58bceSdan    execsql {
92933d58bceSdan      CREATE TABLE t1(a INTEGER PRIMARY KEY, b BLOB);
93033d58bceSdan      BEGIN;
93133d58bceSdan        INSERT INTO t1 VALUES(NULL, randomblob(200));
93233d58bceSdan        INSERT INTO t1 SELECT NULL, randomblob(200) FROM t1;
93333d58bceSdan        INSERT INTO t1 SELECT NULL, randomblob(200) FROM t1;
93433d58bceSdan        INSERT INTO t1 SELECT NULL, randomblob(200) FROM t1;
93533d58bceSdan        INSERT INTO t1 SELECT NULL, randomblob(200) FROM t1;
93633d58bceSdan        INSERT INTO t1 SELECT NULL, randomblob(200) FROM t1;
93733d58bceSdan        INSERT INTO t1 SELECT NULL, randomblob(200) FROM t1;
93833d58bceSdan        INSERT INTO t1 SELECT NULL, randomblob(200) FROM t1;
93933d58bceSdan        INSERT INTO t1 SELECT NULL, randomblob(200) FROM t1;
94033d58bceSdan      COMMIT;
94133d58bceSdan      SELECT count(*) FROM t1;
94233d58bceSdan    }
94333d58bceSdan  } {256}
94433d58bceSdan
94533d58bceSdan  do_test backup-10.$tn.2 {
94633d58bceSdan    set pgs [execsql {pragma page_count}]
94733d58bceSdan    expr {$pgs > 50 && $pgs < 75}
94833d58bceSdan  } {1}
94933d58bceSdan
95033d58bceSdan  do_test backup-10.$tn.3 {
951fda06befSmistachkin    forcedelete bak.db bak.db-journal
95233d58bceSdan    sqlite3 db2 bak.db
95333d58bceSdan    sqlite3_backup B db2 main db main
95433d58bceSdan    B step 50
95533d58bceSdan  } {SQLITE_OK}
95633d58bceSdan
95733d58bceSdan  do_test backup-10.$tn.4 {
95833d58bceSdan    execsql { UPDATE t1 SET b = randomblob(200) WHERE a IN (1, 250) }
95933d58bceSdan  } {}
96033d58bceSdan
96133d58bceSdan  do_test backup-10.$tn.5 {
96233d58bceSdan    B step 50
96333d58bceSdan  } $rc
96433d58bceSdan
965942179f3Sshaneh  do_test backup-10.$tn.6 {
96633d58bceSdan    B finish
96733d58bceSdan  } {SQLITE_OK}
96833d58bceSdan
96933d58bceSdan  db2 close
970942179f3Sshaneh}
971942179f3Sshaneh
972*92ecf306Sdrh# 2021-01-31 https://sqlite.org/forum/forumpost/8b39fbf3e7
973*92ecf306Sdrh#
974*92ecf306Sdrhdo_test backup-11.1 {
975*92ecf306Sdrh  sqlite3 db1 :memory:
976*92ecf306Sdrh  sqlite3 db2 :memory:
977*92ecf306Sdrh  sqlite3_backup B db1 main db2 temp
978*92ecf306Sdrh  B finish
979*92ecf306Sdrh} {SQLITE_OK}
980*92ecf306Sdrh
9810410302eSdanielk1977finish_test
982