xref: /sqlite-3.40.0/test/e_walhook.test (revision a690ff36)
16e45e0c8Sdan# 2014 December 04
26e45e0c8Sdan#
36e45e0c8Sdan# The author disclaims copyright to this source code.  In place of
46e45e0c8Sdan# a legal notice, here is a blessing:
56e45e0c8Sdan#
66e45e0c8Sdan#    May you do good and not evil.
76e45e0c8Sdan#    May you find forgiveness for yourself and forgive others.
86e45e0c8Sdan#    May you share freely, never taking more than you give.
96e45e0c8Sdan#
106e45e0c8Sdan#***********************************************************************
116e45e0c8Sdan#
126e45e0c8Sdan
136e45e0c8Sdanset testdir [file dirname $argv0]
146e45e0c8Sdansource $testdir/tester.tcl
156e45e0c8Sdansource $testdir/wal_common.tcl
166e45e0c8Sdanset testprefix e_walhook
176e45e0c8Sdan
186e45e0c8Sdan
196e45e0c8Sdan# EVIDENCE-OF: R-00752-43975 The sqlite3_wal_hook() function is used to
206e45e0c8Sdan# register a callback that is invoked each time data is committed to a
216e45e0c8Sdan# database in wal mode.
226e45e0c8Sdan#
236e45e0c8Sdan#   1.1: shows that the wal-hook is not invoked in rollback mode.
246e45e0c8Sdan#   1.2: but is invoked in wal mode.
256e45e0c8Sdan#
266e45e0c8Sdanset ::wal_hook_count 0
276e45e0c8Sdanproc my_wal_hook {args} {
286e45e0c8Sdan  incr ::wal_hook_count
296e45e0c8Sdan  return 0
306e45e0c8Sdan}
316e45e0c8Sdan
326e45e0c8Sdando_test 1.1.1 {
336e45e0c8Sdan  db wal_hook my_wal_hook
346e45e0c8Sdan  execsql {
356e45e0c8Sdan    CREATE TABLE t1(x);
366e45e0c8Sdan    INSERT INTO t1 VALUES(1);
376e45e0c8Sdan  }
386e45e0c8Sdan  set ::wal_hook_count
396e45e0c8Sdan} 0
406e45e0c8Sdando_test 1.1.2 {
416e45e0c8Sdan  execsql { PRAGMA journal_mode = wal }
426e45e0c8Sdan  set ::wal_hook_count
436e45e0c8Sdan} 0
446e45e0c8Sdan
456e45e0c8Sdando_test 1.3 {
466e45e0c8Sdan  execsql { INSERT INTO t1 VALUES(2) }
476e45e0c8Sdan  set wal_hook_count
486e45e0c8Sdan} 1
496e45e0c8Sdan
506e45e0c8Sdando_test 1.4 {
516e45e0c8Sdan  execsql {
526e45e0c8Sdan    BEGIN;
536e45e0c8Sdan      INSERT INTO t1 VALUES(3);
546e45e0c8Sdan      INSERT INTO t1 VALUES(4);
556e45e0c8Sdan    COMMIT;
566e45e0c8Sdan  }
576e45e0c8Sdan  set wal_hook_count
586e45e0c8Sdan} 2
596e45e0c8Sdan
606e45e0c8Sdan# EVIDENCE-OF: R-65366-15139 The callback is invoked by SQLite after the
616e45e0c8Sdan# commit has taken place and the associated write-lock on the database
626e45e0c8Sdan# released
636e45e0c8Sdan#
646e45e0c8Sdanset ::read_ok 0
656e45e0c8Sdanproc my_wal_hook {args} {
666e45e0c8Sdan  sqlite3 db2 test.db
676e45e0c8Sdan  if {[db2 eval { SELECT * FROM t1 }] == "1 2 3 4 5"} {
686e45e0c8Sdan    set ::read_ok 1
696e45e0c8Sdan  }
706e45e0c8Sdan  db2 close
716e45e0c8Sdan}
726e45e0c8Sdando_test 2.1 {
736e45e0c8Sdan  execsql { INSERT INTO t1 VALUES(5) }
746e45e0c8Sdan  set ::read_ok
756e45e0c8Sdan} 1
766e45e0c8Sdan
776e45e0c8Sdan# EVIDENCE-OF: R-44294-52863 The third parameter is the name of the
786e45e0c8Sdan# database that was written to - either "main" or the name of an
796e45e0c8Sdan# ATTACH-ed database.
806e45e0c8Sdan#
816e45e0c8Sdan# EVIDENCE-OF: R-18913-19355 The fourth parameter is the number of pages
826e45e0c8Sdan# currently in the write-ahead log file, including those that were just
836e45e0c8Sdan# committed.
846e45e0c8Sdan#
856e45e0c8Sdanset ::wal_hook_args [list]
866e45e0c8Sdanproc my_wal_hook {dbname nEntry} {
876e45e0c8Sdan  set ::wal_hook_args [list $dbname $nEntry]
886e45e0c8Sdan}
896e45e0c8Sdanforcedelete test.db2
906e45e0c8Sdando_test 3.0 {
916e45e0c8Sdan  execsql {
926e45e0c8Sdan    ATTACH 'test.db2' AS aux;
936e45e0c8Sdan    CREATE TABLE aux.t2(x);
946e45e0c8Sdan    PRAGMA aux.journal_mode = wal;
956e45e0c8Sdan  }
966e45e0c8Sdan} {wal}
976e45e0c8Sdan
986e45e0c8Sdan# Database "aux"
996e45e0c8Sdando_test 3.1.1 {
1006e45e0c8Sdan  set wal_hook_args [list]
1016e45e0c8Sdan  execsql { INSERT INTO t2 VALUES('a') }
1026e45e0c8Sdan} {}
1036e45e0c8Sdando_test 3.1.2 {
1046e45e0c8Sdan  set wal_hook_args
1056e45e0c8Sdan} [list aux [wal_frame_count test.db2-wal 1024]]
1066e45e0c8Sdan
1076e45e0c8Sdan# Database "main"
1086e45e0c8Sdando_test 3.2.1 {
1096e45e0c8Sdan  set wal_hook_args [list]
1106e45e0c8Sdan  execsql { INSERT INTO t1 VALUES(6) }
1116e45e0c8Sdan} {}
1126e45e0c8Sdando_test 3.1.2 {
1136e45e0c8Sdan  set wal_hook_args
1146e45e0c8Sdan} [list main [wal_frame_count test.db-wal 1024]]
1156e45e0c8Sdan
1166e45e0c8Sdan# EVIDENCE-OF: R-14034-00929 If an error code is returned, that error
1176e45e0c8Sdan# will propagate back up through the SQLite code base to cause the
1186e45e0c8Sdan# statement that provoked the callback to report an error, though the
1196e45e0c8Sdan# commit will have still occurred.
1206e45e0c8Sdan#
1216e45e0c8Sdanproc my_wal_hook {args} { return 1 ;# SQLITE_ERROR }
1226e45e0c8Sdando_catchsql_test 4.1 {
1236e45e0c8Sdan  INSERT INTO t1 VALUES(7)
124*a690ff36Sdrh} {1 {SQL logic error}}
1256e45e0c8Sdan
1266e45e0c8Sdanproc my_wal_hook {args} { return 5 ;# SQLITE_BUSY }
1276e45e0c8Sdando_catchsql_test 4.2 {
1286e45e0c8Sdan  INSERT INTO t1 VALUES(8)
1296e45e0c8Sdan} {1 {database is locked}}
1306e45e0c8Sdan
1316e45e0c8Sdanproc my_wal_hook {args} { return 14 ;# SQLITE_CANTOPEN }
1326e45e0c8Sdando_catchsql_test 4.3 {
1336e45e0c8Sdan  INSERT INTO t1 VALUES(9)
1346e45e0c8Sdan} {1 {unable to open database file}}
1356e45e0c8Sdan
1366e45e0c8Sdando_execsql_test 4.4 {
1376e45e0c8Sdan  SELECT * FROM t1
1386e45e0c8Sdan} {1 2 3 4 5 6 7 8 9}
1396e45e0c8Sdan
1406e45e0c8Sdan# EVIDENCE-OF: R-10466-53920 Calling sqlite3_wal_hook() replaces any
1416e45e0c8Sdan# previously registered write-ahead log callback.
1426e45e0c8Sdanset ::old_wal_hook 0
1436e45e0c8Sdanproc my_old_wal_hook {args} {
1446e45e0c8Sdan  incr ::old_wal_hook
1456e45e0c8Sdan  return 0
1466e45e0c8Sdan}
1476e45e0c8Sdandb wal_hook my_old_wal_hook
1486e45e0c8Sdando_test 5.1 {
1496e45e0c8Sdan  execsql { INSERT INTO t1 VALUES(10) }
1506e45e0c8Sdan  set ::old_wal_hook
1516e45e0c8Sdan} {1}
1526e45e0c8Sdan
1536e45e0c8Sdan# Replace old_wal_hook. Observe that it is not invoked after it has
1546e45e0c8Sdan# been replaced.
1556e45e0c8Sdanproc my_new_wal_hook {args} { return 0 }
1566e45e0c8Sdandb wal_hook my_new_wal_hook
1576e45e0c8Sdando_test 5.2 {
1586e45e0c8Sdan  execsql { INSERT INTO t1 VALUES(11) }
1596e45e0c8Sdan  set ::old_wal_hook
1606e45e0c8Sdan} {1}
1616e45e0c8Sdan
1626e45e0c8Sdan
1636e45e0c8Sdan
1644f8f5e44Sdrh# EVIDENCE-OF: R-57445-43425 Note that the sqlite3_wal_autocheckpoint()
1656e45e0c8Sdan# interface and the wal_autocheckpoint pragma both invoke
1664f8f5e44Sdrh# sqlite3_wal_hook() and will overwrite any prior sqlite3_wal_hook()
1674f8f5e44Sdrh# settings.
1686e45e0c8Sdan#
1696e45e0c8Sdanset ::old_wal_hook 0
1706e45e0c8Sdanproc my_old_wal_hook {args} { incr ::old_wal_hook ; return 0 }
1711f03b865Sdandb wal_hook my_old_wal_hook
1726e45e0c8Sdando_test 6.1.1 {
1736e45e0c8Sdan  execsql { INSERT INTO t1 VALUES(12) }
1746e45e0c8Sdan  set ::old_wal_hook
1756e45e0c8Sdan} {1}
1766e45e0c8Sdando_test 6.1.2 {
1771f03b865Sdan  execsql { PRAGMA wal_autocheckpoint = 1000 }
1786e45e0c8Sdan  execsql { INSERT INTO t1 VALUES(12) }
1796e45e0c8Sdan  set ::old_wal_hook
1806e45e0c8Sdan} {1}
1816e45e0c8Sdan
1826e45e0c8Sdan# EVIDENCE-OF: R-52629-38967 The first parameter passed to the callback
1836e45e0c8Sdan# function when it is invoked is a copy of the third parameter passed to
1846e45e0c8Sdan# sqlite3_wal_hook() when registering the callback.
1856e45e0c8Sdan#
1866e45e0c8Sdan#    This is tricky to test using the tcl interface. However, the
1876e45e0c8Sdan#    mechanism used to invoke the tcl script registered as a wal-hook
1886e45e0c8Sdan#    depends on the context pointer being correctly passed through. And
1896e45e0c8Sdan#    since multiple different wal-hook scripts have been successfully
1906e45e0c8Sdan#    invoked by this test script, consider this tested.
1916e45e0c8Sdan#
1926e45e0c8Sdan# EVIDENCE-OF: R-23378-42536 The second is a copy of the database
1936e45e0c8Sdan# handle.
1946e45e0c8Sdan#
1956e45e0c8Sdan#    There is an assert() in the C wal-hook used by tclsqlite.c to
1966e45e0c8Sdan#    prove this. And that hook has been invoked multiple times when
1976e45e0c8Sdan#    running this script. So consider this requirement tested as well.
1986e45e0c8Sdan#
1996e45e0c8Sdan
2006e45e0c8Sdanfinish_test
201