xref: /sqlite-3.40.0/test/e_walauto.test (revision 7da56b4f)
19af10620Sdan# 2014 December 04
29af10620Sdan#
39af10620Sdan# The author disclaims copyright to this source code.  In place of
49af10620Sdan# a legal notice, here is a blessing:
59af10620Sdan#
69af10620Sdan#    May you do good and not evil.
79af10620Sdan#    May you find forgiveness for yourself and forgive others.
89af10620Sdan#    May you share freely, never taking more than you give.
99af10620Sdan#
109af10620Sdan#***********************************************************************
119af10620Sdan#
129af10620Sdan
139af10620Sdanset testdir [file dirname $argv0]
149af10620Sdansource $testdir/tester.tcl
159af10620Sdansource $testdir/wal_common.tcl
169af10620Sdanset testprefix e_walauto
179af10620Sdan
185f1731f6Sdan# Do not run this test on OpenBSD, as it depends on read() and mmap both
195f1731f6Sdan# accessing the same coherent view of the "test.db-shm" file. This doesn't
205f1731f6Sdan# work on OpenBSD.
215f1731f6Sdan#
225f1731f6Sdanif {$tcl_platform(os) == "OpenBSD"} {
235f1731f6Sdan  finish_test
245f1731f6Sdan  return
255f1731f6Sdan}
269af10620Sdan
27*7da56b4fSdrh# This module uses hard-coded offsets which do not work if the reserved_bytes
28*7da56b4fSdrh# value is nonzero.
29*7da56b4fSdrhif {[nonzero_reserved_bytes]} {finish_test; return;}
30*7da56b4fSdrh
31*7da56b4fSdrh
329af10620Sdanproc read_nbackfill {} {
339af10620Sdan  seek $::shmfd 96
34e0e43029Sdrh  binary scan [read $::shmfd 4] n nBackfill
359af10620Sdan  set nBackfill
369af10620Sdan}
379af10620Sdanproc read_mxframe {} {
389af10620Sdan  seek $::shmfd 16
39e0e43029Sdrh  binary scan [read $::shmfd 4] n mxFrame
409af10620Sdan  set mxFrame
419af10620Sdan}
429af10620Sdan
439af10620Sdan# Assuming that the main db for database handle
449af10620Sdan#
459af10620Sdanproc do_autocommit_threshold_test {tn value} {
469af10620Sdan
479af10620Sdan  set nBackfillSaved [read_nbackfill]
489af10620Sdan  while {1} {
499af10620Sdan    db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) }
509af10620Sdan    if {[read_mxframe] >= $value} break
519af10620Sdan  }
529af10620Sdan
539af10620Sdan  set nBackfillNew [read_nbackfill]
549af10620Sdan  uplevel [list do_test $tn "expr $nBackfillNew > $nBackfillSaved" 1]
559af10620Sdan}
569af10620Sdan
579af10620Sdan# EVIDENCE-OF: R-30135-06439 The wal_autocheckpoint pragma can be used
589af10620Sdan# to invoke this interface from SQL.
599af10620Sdan#
609af10620Sdan#   All tests in this file are run twice - once using the
619af10620Sdan#   sqlite3_wal_autocheckpoint() API, and once using "PRAGMA
629af10620Sdan#   wal_autocheckpoint".
639af10620Sdan#
649af10620Sdanforeach {tn code} {
659af10620Sdan  1 {
669af10620Sdan    proc autocheckpoint {db value} {
679af10620Sdan      uplevel [list $db eval "PRAGMA wal_autocheckpoint = $value"]
689af10620Sdan    }
699af10620Sdan  }
709af10620Sdan
719af10620Sdan  2 {
729af10620Sdan    proc autocheckpoint {db value} {
739af10620Sdan      uplevel [list sqlite3_wal_autocheckpoint $db $value]
749af10620Sdan      return $value
759af10620Sdan    }
769af10620Sdan  }
779af10620Sdan} {
789af10620Sdan
799af10620Sdan  eval $code
809af10620Sdan
819af10620Sdan  reset_db
8262031584Sdan  execsql { PRAGMA auto_vacuum = 0 }
839af10620Sdan  do_execsql_test 1.$tn.0 { PRAGMA journal_mode = WAL } {wal}
849af10620Sdan  do_execsql_test 1.$tn.1 { CREATE TABLE t1(a, b) }
85e8d1777aSdrh  set shmfd [open "test.db-shm" rb]
869af10620Sdan
879af10620Sdan  # EVIDENCE-OF: R-41531-51083 Every new database connection defaults to
889af10620Sdan  # having the auto-checkpoint enabled with a threshold of 1000 or
899af10620Sdan  # SQLITE_DEFAULT_WAL_AUTOCHECKPOINT pages.
909af10620Sdan  #
919af10620Sdan  do_autocommit_threshold_test 1.$tn.2 1000
929af10620Sdan  db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) }
939af10620Sdan  do_autocommit_threshold_test 1.$tn.3 1000
949af10620Sdan
959af10620Sdan  # EVIDENCE-OF: R-38128-34102 The sqlite3_wal_autocheckpoint(D,N) is a
969af10620Sdan  # wrapper around sqlite3_wal_hook() that causes any database on database
979af10620Sdan  # connection D to automatically checkpoint after committing a
989af10620Sdan  # transaction if there are N or more frames in the write-ahead log file.
999af10620Sdan  #
1009af10620Sdan  do_test 1.$tn.4 {
1019af10620Sdan    db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) }
1029af10620Sdan    autocheckpoint db 100
1039af10620Sdan  } {100}
1049af10620Sdan  do_autocommit_threshold_test 1.$tn.5 100
1059af10620Sdan
1069af10620Sdan  do_test 1.$tn.6 {
1079af10620Sdan    db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) }
1089af10620Sdan    autocheckpoint db 500
1099af10620Sdan  } {500}
1109af10620Sdan  do_autocommit_threshold_test 1.$tn.7 500
1119af10620Sdan
1129af10620Sdan  # EVIDENCE-OF: R-26993-43540 Passing zero or a negative value as the
1139af10620Sdan  # nFrame parameter disables automatic checkpoints entirely.
1149af10620Sdan  #
1159af10620Sdan  do_test 1.$tn.7 {
1169af10620Sdan    autocheckpoint db 0    ;# Set to zero
1179af10620Sdan    for {set i 0} {$i < 10000} {incr i} {
1189af10620Sdan      db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) }
1199af10620Sdan    }
1209af10620Sdan    expr {[file size test.db-wal] > (5 * 1024 * 1024)}
1219af10620Sdan  } 1
1229af10620Sdan  do_test 1.$tn.8 {
1239af10620Sdan    sqlite3_wal_checkpoint_v2 db truncate
1249af10620Sdan    file size test.db-wal
1259af10620Sdan  } 0
1269af10620Sdan  do_test 1.$tn.9 {
1279af10620Sdan    autocheckpoint db -4    ;# Set to a negative value
1289af10620Sdan    for {set i 0} {$i < 10000} {incr i} {
1299af10620Sdan      db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) }
1309af10620Sdan    }
1319af10620Sdan    expr {[file size test.db-wal] > (5 * 1024 * 1024)}
1329af10620Sdan  } 1
1339af10620Sdan
1349af10620Sdan  # EVIDENCE-OF: R-10203-42688 The callback registered by this function
1359af10620Sdan  # replaces any existing callback registered using sqlite3_wal_hook().
1369af10620Sdan  #
1379af10620Sdan  set ::wal_hook_callback 0
1389af10620Sdan  proc wal_hook_callback {args} { incr ::wal_hook_callback ; return 0 }
1399af10620Sdan  do_test 1.$tn.10.1 {
1409af10620Sdan    db wal_hook wal_hook_callback
1419af10620Sdan    db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) }
1429af10620Sdan    db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) }
1439af10620Sdan    set ::wal_hook_callback
1449af10620Sdan  } 2
1459af10620Sdan  do_test 1.$tn.10.2 {
1469af10620Sdan    autocheckpoint db 100
1479af10620Sdan    db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) }
1489af10620Sdan    db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) }
1499af10620Sdan    set ::wal_hook_callback
1509af10620Sdan  } 2
1519af10620Sdan
1529af10620Sdan  # EVIDENCE-OF: R-17497-43474 Likewise, registering a callback using
1539af10620Sdan  # sqlite3_wal_hook() disables the automatic checkpoint mechanism
1549af10620Sdan  # configured by this function.
1559af10620Sdan  do_test 1.$tn.11.1 {
1569af10620Sdan    sqlite3_wal_checkpoint_v2 db truncate
1579af10620Sdan    file size test.db-wal
1589af10620Sdan  } 0
1599af10620Sdan  do_test 1.$tn.11.2 {
1609af10620Sdan    autocheckpoint db 100
1619af10620Sdan    for {set i 0} {$i < 1000} {incr i} {
1629af10620Sdan      db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) }
1639af10620Sdan    }
1649af10620Sdan    expr {[file size test.db-wal] < (1 * 1024 * 1024)}
1659af10620Sdan  } 1
1669af10620Sdan  do_test 1.$tn.11.3 {
1679af10620Sdan    db wal_hook wal_hook_callback
1689af10620Sdan    for {set i 0} {$i < 1000} {incr i} {
1699af10620Sdan      db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) }
1709af10620Sdan    }
1719af10620Sdan    expr {[file size test.db-wal] < (1 * 1024 * 1024)}
1729af10620Sdan  } 0
1739af10620Sdan
1749af10620Sdan  # EVIDENCE-OF: R-33080-59193 Checkpoints initiated by this mechanism
1759af10620Sdan  # are PASSIVE.
1769af10620Sdan  #
1779af10620Sdan  set ::busy_callback_count 0
1789af10620Sdan  proc busy_callback {args} {
1799af10620Sdan    incr ::busy_callback_count
1809af10620Sdan    return 0
1819af10620Sdan  }
1829af10620Sdan  do_test 1.$tn.12.1 {
1839af10620Sdan    sqlite3_wal_checkpoint_v2 db truncate
1849af10620Sdan    autocheckpoint db 100
1859af10620Sdan    db busy busy_callback
1869af10620Sdan    db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) }
1879af10620Sdan    db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) }
1889af10620Sdan  } {}
1899af10620Sdan  do_test 1.$tn.12.2 {
1909af10620Sdan    sqlite3 db2 test.db
1919af10620Sdan    db2 eval { BEGIN; SELECT * FROM t1 LIMIT 10; }
1929af10620Sdan    read_nbackfill
1939af10620Sdan  } {0}
1949af10620Sdan  do_test 1.$tn.12.3 {
1959af10620Sdan    for {set i 0} {$i < 1000} {incr i} {
1969af10620Sdan      db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) }
1979af10620Sdan    }
1989af10620Sdan    read_nbackfill
1999af10620Sdan  } {2}
2009af10620Sdan  do_test 1.$tn.12.4 {
2019af10620Sdan    set ::busy_callback_count
2029af10620Sdan  } {0}
2039af10620Sdan  db2 close
2049af10620Sdan
2059af10620Sdan  do_test 1.$tn.12.5 {
2069af10620Sdan    db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) }
2079af10620Sdan    read_nbackfill
2089af10620Sdan  } {1559}
2099af10620Sdan
2109af10620Sdan  db close
2119af10620Sdan  close $shmfd
2129af10620Sdan}
2139af10620Sdan
2149af10620Sdanfinish_test
215