1538f570cSdrh# 2007 April 12 2538f570cSdrh# 3538f570cSdrh# The author disclaims copyright to this source code. In place of 4538f570cSdrh# a legal notice, here is a blessing: 5538f570cSdrh# 6538f570cSdrh# May you do good and not evil. 7538f570cSdrh# May you find forgiveness for yourself and forgive others. 8538f570cSdrh# May you share freely, never taking more than you give. 9538f570cSdrh# 10538f570cSdrh#*********************************************************************** 11538f570cSdrh# This file implements regression tests for SQLite library. 12538f570cSdrh# The focus of the tests in this file are to verify that the 13538f570cSdrh# pager optimizations implemented in version 3.3.14 work. 14538f570cSdrh# 158c0a791aSdanielk1977# $Id: pageropt.test,v 1.5 2008/08/20 14:49:25 danielk1977 Exp $ 16538f570cSdrh 17538f570cSdrhset testdir [file dirname $argv0] 18538f570cSdrhsource $testdir/tester.tcl 197da56b4fSdrhdo_not_use_codec 20538f570cSdrh 21f4ba1093Sdanifcapable {!pager_pragmas||secure_delete||direct_read} { 22538f570cSdrh finish_test 23538f570cSdrh return 24538f570cSdrh} 25538f570cSdrh 26*82f52540Sdrh# A non-zero reserved_bytes value changes the number of pages in the 27*82f52540Sdrh# database file, which messes up the results in this test. 28*82f52540Sdrhif {[nonzero_reserved_bytes]} {finish_test; return;} 29*82f52540Sdrh 30538f570cSdrh# Run the SQL statement supplied by the argument and return 31538f570cSdrh# the results. Prepend four integers to the beginning of the 32538f570cSdrh# result which are 33538f570cSdrh# 34538f570cSdrh# (1) The number of page reads from the database 35538f570cSdrh# (2) The number of page writes to the database 36538f570cSdrh# (3) The number of page writes to the journal 37538f570cSdrh# (4) The number of cache pages freed 38538f570cSdrh# 39538f570cSdrhproc pagercount_sql {sql {db db}} { 40538f570cSdrh global sqlite3_pager_readdb_count 41538f570cSdrh global sqlite3_pager_writedb_count 42538f570cSdrh global sqlite3_pager_writej_count 43538f570cSdrh global sqlite3_pager_pgfree_count 44538f570cSdrh set sqlite3_pager_readdb_count 0 45538f570cSdrh set sqlite3_pager_writedb_count 0 46538f570cSdrh set sqlite3_pager_writej_count 0 47538f570cSdrh set r [$db eval $sql] 48538f570cSdrh set cnt [list $sqlite3_pager_readdb_count \ 49538f570cSdrh $sqlite3_pager_writedb_count \ 508c0a791aSdanielk1977 $sqlite3_pager_writej_count ] 51538f570cSdrh return [concat $cnt $r] 52538f570cSdrh} 53538f570cSdrh 54538f570cSdrh# Setup the test database 55538f570cSdrh# 56538f570cSdrhdo_test pageropt-1.1 { 573aefabafSdrh sqlite3_soft_heap_limit 0 58538f570cSdrh execsql { 59538f570cSdrh PRAGMA auto_vacuum = OFF; 60538f570cSdrh PRAGMA page_size = 1024; 61538f570cSdrh } 62538f570cSdrh pagercount_sql { 63538f570cSdrh CREATE TABLE t1(x); 64538f570cSdrh } 658c0a791aSdanielk1977} {0 2 0} 66538f570cSdrhdo_test pageropt-1.2 { 67538f570cSdrh pagercount_sql { 68538f570cSdrh INSERT INTO t1 VALUES(randomblob(5000)); 69538f570cSdrh } 708c0a791aSdanielk1977} {0 6 2} 71538f570cSdrh 72538f570cSdrh# Verify that values remain in cache on for subsequent reads. 73538f570cSdrh# We should not have to go back to disk. 74538f570cSdrh# 75538f570cSdrhdo_test pageropt-1.3 { 76538f570cSdrh pagercount_sql { 77538f570cSdrh SELECT length(x) FROM t1 78538f570cSdrh } 798c0a791aSdanielk1977} {0 0 0 5000} 80538f570cSdrh 81538f570cSdrh# If another thread reads the database, the original cache 82538f570cSdrh# remains valid. 83538f570cSdrh# 84538f570cSdrhsqlite3 db2 test.db 85538f570cSdrhset blobcontent [db2 one {SELECT hex(x) FROM t1}] 86538f570cSdrhdo_test pageropt-1.4 { 87538f570cSdrh pagercount_sql { 88538f570cSdrh SELECT hex(x) FROM t1 89538f570cSdrh } 908c0a791aSdanielk1977} [list 0 0 0 $blobcontent] 91538f570cSdrh 92538f570cSdrh# But if the other thread modifies the database, then the cache 93538f570cSdrh# must refill. 94538f570cSdrh# 95188d4884Sdrhifcapable mmap { 969b4c59faSdrh set x [expr {[permutation]=="mmap" ? 1 : 6}] 97188d4884Sdrh} else { 98188d4884Sdrh set x 6 99188d4884Sdrh} 100538f570cSdrhdo_test pageropt-1.5 { 101538f570cSdrh db2 eval {CREATE TABLE t2(y)} 102538f570cSdrh pagercount_sql { 103538f570cSdrh SELECT hex(x) FROM t1 104538f570cSdrh } 105188d4884Sdrh} [list $x 0 0 $blobcontent] 106538f570cSdrhdo_test pageropt-1.6 { 107538f570cSdrh pagercount_sql { 108538f570cSdrh SELECT hex(x) FROM t1 109538f570cSdrh } 1108c0a791aSdanielk1977} [list 0 0 0 $blobcontent] 111538f570cSdrh 112538f570cSdrh# Verify that the last page of an overflow chain is not read from 113538f570cSdrh# disk when deleting a row. The one row of t1(x) has four pages 114538f570cSdrh# of overflow. So deleting that row from t1 should involve reading 115538f570cSdrh# the sqlite_master table (1 page) the main page of t1 (1 page) and 116538f570cSdrh# the three overflow pages of t1 for a total of 5 pages. 117538f570cSdrh# 118538f570cSdrh# Pages written are page 1 (for the freelist pointer), the root page 119538f570cSdrh# of the table, and one of the overflow chain pointers because it 120538f570cSdrh# becomes the trunk of the freelist. Total 3. 121538f570cSdrh# 122538f570cSdrhdo_test pageropt-2.1 { 123538f570cSdrh db close 124538f570cSdrh sqlite3 db test.db 125538f570cSdrh pagercount_sql { 126538f570cSdrh DELETE FROM t1 WHERE rowid=1 127538f570cSdrh } 1288c0a791aSdanielk1977} {5 3 3} 129538f570cSdrh 130538f570cSdrh# When pulling pages off of the freelist, there is no reason 131538f570cSdrh# to actually bring in the old content. 132538f570cSdrh# 133538f570cSdrhdo_test pageropt-2.2 { 134538f570cSdrh db close 135538f570cSdrh sqlite3 db test.db 136538f570cSdrh pagercount_sql { 137538f570cSdrh INSERT INTO t1 VALUES(randomblob(1500)); 138538f570cSdrh } 1398c0a791aSdanielk1977} {3 4 3} 140538f570cSdrhdo_test pageropt-2.3 { 141538f570cSdrh pagercount_sql { 142538f570cSdrh INSERT INTO t1 VALUES(randomblob(1500)); 143538f570cSdrh } 1448c0a791aSdanielk1977} {0 4 3} 145538f570cSdrh 1466558db80Sdrh# Note the new optimization that when pulling the very last page off of the 1476558db80Sdrh# freelist we do not read the content of that page. 1486558db80Sdrh# 1496558db80Sdrhdo_test pageropt-2.4 { 1506558db80Sdrh pagercount_sql { 1516558db80Sdrh INSERT INTO t1 VALUES(randomblob(1500)); 1526558db80Sdrh } 1538c0a791aSdanielk1977} {0 5 3} 1546558db80Sdrh 1556558db80Sdrh# Appending a large quantity of data does not involve writing much 1566558db80Sdrh# to the journal file. 1576558db80Sdrh# 1586558db80Sdrhdo_test pageropt-3.1 { 1596558db80Sdrh pagercount_sql { 1606558db80Sdrh INSERT INTO t2 SELECT * FROM t1; 1616558db80Sdrh } 1628c0a791aSdanielk1977} {1 7 2} 1636558db80Sdrh 1646558db80Sdrh# Once again, we do not need to read the last page of an overflow chain 1656558db80Sdrh# while deleting. 1666558db80Sdrh# 1676558db80Sdrhdo_test pageropt-3.2 { 1686558db80Sdrh pagercount_sql { 1696558db80Sdrh DROP TABLE t2; 1706558db80Sdrh } 1718c0a791aSdanielk1977} {0 2 3} 1726558db80Sdrhdo_test pageropt-3.3 { 1736558db80Sdrh pagercount_sql { 1746558db80Sdrh DELETE FROM t1; 1756558db80Sdrh } 1768c0a791aSdanielk1977} {0 3 3} 1776558db80Sdrh 1786558db80Sdrh# There are now 11 pages on the freelist. Move them all into an 1796558db80Sdrh# overflow chain by inserting a single large record. Starting from 1806558db80Sdrh# a cold cache, only page 1, the root page of table t1, and the trunk 1816558db80Sdrh# of the freelist need to be read (3 pages). And only those three 1826558db80Sdrh# pages need to be journalled. But 13 pages need to be written: 1836558db80Sdrh# page1, the root page of table t1, and an 11 page overflow chain. 1846558db80Sdrh# 1856558db80Sdrhdo_test pageropt-4.1 { 1866558db80Sdrh db close 1876558db80Sdrh sqlite3 db test.db 1886558db80Sdrh pagercount_sql { 1896558db80Sdrh INSERT INTO t1 VALUES(randomblob(11300)) 1906558db80Sdrh } 1918c0a791aSdanielk1977} {3 13 3} 1926558db80Sdrh 1936558db80Sdrh# Now we delete that big entries starting from a cold cache and an 1946558db80Sdrh# empty freelist. The first 10 of the 11 pages overflow chain have 1956558db80Sdrh# to be read, together with page1 and the root of the t1 table. 12 1966558db80Sdrh# reads total. But only page1, the t1 root, and the trunk of the 1976558db80Sdrh# freelist need to be journalled and written back. 1986558db80Sdrh# 199c5d0bd90Sdrhdo_test pageropt-4.2 { 2006558db80Sdrh db close 2016558db80Sdrh sqlite3 db test.db 2026558db80Sdrh pagercount_sql { 2036558db80Sdrh DELETE FROM t1 2046558db80Sdrh } 2058c0a791aSdanielk1977} {12 3 3} 2066558db80Sdrh 207c1a60c51Sdansqlite3_soft_heap_limit $cmdlinearg(soft-heap-limit) 208538f570cSdrhcatch {db2 close} 209538f570cSdrhfinish_test 210