210 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			210 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| # 2014 December 04
 | |
| #
 | |
| # The author disclaims copyright to this source code.  In place of
 | |
| # a legal notice, here is a blessing:
 | |
| #
 | |
| #    May you do good and not evil.
 | |
| #    May you find forgiveness for yourself and forgive others.
 | |
| #    May you share freely, never taking more than you give.
 | |
| #
 | |
| #***********************************************************************
 | |
| #
 | |
| 
 | |
| set testdir [file dirname $argv0]
 | |
| source $testdir/tester.tcl
 | |
| source $testdir/wal_common.tcl
 | |
| set testprefix e_walauto
 | |
| 
 | |
| # Do not run this test on OpenBSD, as it depends on read() and mmap both
 | |
| # accessing the same coherent view of the "test.db-shm" file. This doesn't
 | |
| # work on OpenBSD.
 | |
| #
 | |
| if {$tcl_platform(os) == "OpenBSD"} {
 | |
|   finish_test
 | |
|   return
 | |
| }
 | |
| 
 | |
| proc read_nbackfill {} {
 | |
|   seek $::shmfd 96
 | |
|   binary scan [read $::shmfd 4] n nBackfill
 | |
|   set nBackfill
 | |
| }
 | |
| proc read_mxframe {} {
 | |
|   seek $::shmfd 16
 | |
|   binary scan [read $::shmfd 4] n mxFrame
 | |
|   set mxFrame
 | |
| }
 | |
| 
 | |
| # Assuming that the main db for database handle
 | |
| #
 | |
| proc do_autocommit_threshold_test {tn value} {
 | |
| 
 | |
|   set nBackfillSaved [read_nbackfill]
 | |
|   while {1} {
 | |
|     db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) }
 | |
|     if {[read_mxframe] >= $value} break
 | |
|   }
 | |
|   
 | |
|   set nBackfillNew [read_nbackfill]
 | |
|   uplevel [list do_test $tn "expr $nBackfillNew > $nBackfillSaved" 1]
 | |
| }
 | |
| 
 | |
| # EVIDENCE-OF: R-30135-06439 The wal_autocheckpoint pragma can be used
 | |
| # to invoke this interface from SQL.
 | |
| #
 | |
| #   All tests in this file are run twice - once using the
 | |
| #   sqlite3_wal_autocheckpoint() API, and once using "PRAGMA
 | |
| #   wal_autocheckpoint".
 | |
| #
 | |
| foreach {tn code} {
 | |
|   1 {
 | |
|     proc autocheckpoint {db value} {
 | |
|       uplevel [list $db eval "PRAGMA wal_autocheckpoint = $value"]
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   2 {
 | |
|     proc autocheckpoint {db value} {
 | |
|       uplevel [list sqlite3_wal_autocheckpoint $db $value]
 | |
|       return $value
 | |
|     }
 | |
|   }
 | |
| } {
 | |
| 
 | |
|   eval $code
 | |
| 
 | |
|   reset_db
 | |
|   execsql { PRAGMA auto_vacuum = 0 }
 | |
|   do_execsql_test 1.$tn.0 { PRAGMA journal_mode = WAL } {wal}
 | |
|   do_execsql_test 1.$tn.1 { CREATE TABLE t1(a, b) }
 | |
|   set shmfd [open "test.db-shm" rb]
 | |
| 
 | |
|   # EVIDENCE-OF: R-41531-51083 Every new database connection defaults to
 | |
|   # having the auto-checkpoint enabled with a threshold of 1000 or
 | |
|   # SQLITE_DEFAULT_WAL_AUTOCHECKPOINT pages.
 | |
|   #
 | |
|   do_autocommit_threshold_test 1.$tn.2 1000
 | |
|   db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) }
 | |
|   do_autocommit_threshold_test 1.$tn.3 1000
 | |
| 
 | |
|   # EVIDENCE-OF: R-38128-34102 The sqlite3_wal_autocheckpoint(D,N) is a
 | |
|   # wrapper around sqlite3_wal_hook() that causes any database on database
 | |
|   # connection D to automatically checkpoint after committing a
 | |
|   # transaction if there are N or more frames in the write-ahead log file.
 | |
|   #
 | |
|   do_test 1.$tn.4 {
 | |
|     db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) }
 | |
|     autocheckpoint db 100
 | |
|   } {100}
 | |
|   do_autocommit_threshold_test 1.$tn.5 100
 | |
| 
 | |
|   do_test 1.$tn.6 {
 | |
|     db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) }
 | |
|     autocheckpoint db 500
 | |
|   } {500}
 | |
|   do_autocommit_threshold_test 1.$tn.7 500
 | |
| 
 | |
|   # EVIDENCE-OF: R-26993-43540 Passing zero or a negative value as the
 | |
|   # nFrame parameter disables automatic checkpoints entirely.
 | |
|   #
 | |
|   do_test 1.$tn.7 {
 | |
|     autocheckpoint db 0    ;# Set to zero
 | |
|     for {set i 0} {$i < 10000} {incr i} {
 | |
|       db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) }
 | |
|     }
 | |
|     expr {[file size test.db-wal] > (5 * 1024 * 1024)}
 | |
|   } 1
 | |
|   do_test 1.$tn.8 {
 | |
|     sqlite3_wal_checkpoint_v2 db truncate
 | |
|     file size test.db-wal
 | |
|   } 0
 | |
|   do_test 1.$tn.9 {
 | |
|     autocheckpoint db -4    ;# Set to a negative value
 | |
|     for {set i 0} {$i < 10000} {incr i} {
 | |
|       db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) }
 | |
|     }
 | |
|     expr {[file size test.db-wal] > (5 * 1024 * 1024)}
 | |
|   } 1
 | |
| 
 | |
|   # EVIDENCE-OF: R-10203-42688 The callback registered by this function
 | |
|   # replaces any existing callback registered using sqlite3_wal_hook().
 | |
|   #
 | |
|   set ::wal_hook_callback 0
 | |
|   proc wal_hook_callback {args} { incr ::wal_hook_callback ; return 0 }
 | |
|   do_test 1.$tn.10.1 {
 | |
|     db wal_hook wal_hook_callback
 | |
|     db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) }
 | |
|     db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) }
 | |
|     set ::wal_hook_callback
 | |
|   } 2
 | |
|   do_test 1.$tn.10.2 {
 | |
|     autocheckpoint db 100
 | |
|     db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) }
 | |
|     db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) }
 | |
|     set ::wal_hook_callback
 | |
|   } 2
 | |
| 
 | |
|   # EVIDENCE-OF: R-17497-43474 Likewise, registering a callback using
 | |
|   # sqlite3_wal_hook() disables the automatic checkpoint mechanism
 | |
|   # configured by this function.
 | |
|   do_test 1.$tn.11.1 {
 | |
|     sqlite3_wal_checkpoint_v2 db truncate
 | |
|     file size test.db-wal
 | |
|   } 0
 | |
|   do_test 1.$tn.11.2 {
 | |
|     autocheckpoint db 100 
 | |
|     for {set i 0} {$i < 1000} {incr i} {
 | |
|       db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) }
 | |
|     }
 | |
|     expr {[file size test.db-wal] < (1 * 1024 * 1024)}
 | |
|   } 1
 | |
|   do_test 1.$tn.11.3 {
 | |
|     db wal_hook wal_hook_callback
 | |
|     for {set i 0} {$i < 1000} {incr i} {
 | |
|       db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) }
 | |
|     }
 | |
|     expr {[file size test.db-wal] < (1 * 1024 * 1024)}
 | |
|   } 0
 | |
| 
 | |
|   # EVIDENCE-OF: R-33080-59193 Checkpoints initiated by this mechanism 
 | |
|   # are PASSIVE.
 | |
|   #
 | |
|   set ::busy_callback_count 0
 | |
|   proc busy_callback {args} {
 | |
|     incr ::busy_callback_count
 | |
|     return 0
 | |
|   }
 | |
|   do_test 1.$tn.12.1 {
 | |
|     sqlite3_wal_checkpoint_v2 db truncate
 | |
|     autocheckpoint db 100 
 | |
|     db busy busy_callback
 | |
|     db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) }
 | |
|     db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) }
 | |
|   } {}
 | |
|   do_test 1.$tn.12.2 {
 | |
|     sqlite3 db2 test.db
 | |
|     db2 eval { BEGIN; SELECT * FROM t1 LIMIT 10; }
 | |
|     read_nbackfill
 | |
|   } {0}
 | |
|   do_test 1.$tn.12.3 {
 | |
|     for {set i 0} {$i < 1000} {incr i} {
 | |
|       db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) }
 | |
|     }
 | |
|     read_nbackfill
 | |
|   } {2}
 | |
|   do_test 1.$tn.12.4 {
 | |
|     set ::busy_callback_count
 | |
|   } {0}
 | |
|   db2 close
 | |
| 
 | |
|   do_test 1.$tn.12.5 {
 | |
|     db eval { INSERT INTO t1 VALUES(randomblob(100), randomblob(100)) }
 | |
|     read_nbackfill
 | |
|   } {1559}
 | |
| 
 | |
|   db close
 | |
|   close $shmfd
 | |
| }
 | |
| 
 | |
| finish_test
 | 
