pageropt.test 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. # 2007 April 12
  2. #
  3. # The author disclaims copyright to this source code. In place of
  4. # a legal notice, here is a blessing:
  5. #
  6. # May you do good and not evil.
  7. # May you find forgiveness for yourself and forgive others.
  8. # May you share freely, never taking more than you give.
  9. #
  10. #***********************************************************************
  11. # This file implements regression tests for SQLite library.
  12. # The focus of the tests in this file are to verify that the
  13. # pager optimizations implemented in version 3.3.14 work.
  14. #
  15. # $Id: pageropt.test,v 1.5 2008/08/20 14:49:25 danielk1977 Exp $
  16. set testdir [file dirname $argv0]
  17. source $testdir/tester.tcl
  18. ifcapable {!pager_pragmas||secure_delete||direct_read} {
  19. finish_test
  20. return
  21. }
  22. # Run the SQL statement supplied by the argument and return
  23. # the results. Prepend four integers to the beginning of the
  24. # result which are
  25. #
  26. # (1) The number of page reads from the database
  27. # (2) The number of page writes to the database
  28. # (3) The number of page writes to the journal
  29. # (4) The number of cache pages freed
  30. #
  31. proc pagercount_sql {sql {db db}} {
  32. global sqlite3_pager_readdb_count
  33. global sqlite3_pager_writedb_count
  34. global sqlite3_pager_writej_count
  35. global sqlite3_pager_pgfree_count
  36. set sqlite3_pager_readdb_count 0
  37. set sqlite3_pager_writedb_count 0
  38. set sqlite3_pager_writej_count 0
  39. set r [$db eval $sql]
  40. set cnt [list $sqlite3_pager_readdb_count \
  41. $sqlite3_pager_writedb_count \
  42. $sqlite3_pager_writej_count ]
  43. return [concat $cnt $r]
  44. }
  45. # Setup the test database
  46. #
  47. do_test pageropt-1.1 {
  48. sqlite3_soft_heap_limit 0
  49. execsql {
  50. PRAGMA auto_vacuum = OFF;
  51. PRAGMA page_size = 1024;
  52. }
  53. pagercount_sql {
  54. CREATE TABLE t1(x);
  55. }
  56. } {0 2 0}
  57. do_test pageropt-1.2 {
  58. pagercount_sql {
  59. INSERT INTO t1 VALUES(randomblob(5000));
  60. }
  61. } {0 6 2}
  62. # Verify that values remain in cache on for subsequent reads.
  63. # We should not have to go back to disk.
  64. #
  65. do_test pageropt-1.3 {
  66. pagercount_sql {
  67. SELECT length(x) FROM t1
  68. }
  69. } {0 0 0 5000}
  70. # If another thread reads the database, the original cache
  71. # remains valid.
  72. #
  73. sqlite3 db2 test.db
  74. set blobcontent [db2 one {SELECT hex(x) FROM t1}]
  75. do_test pageropt-1.4 {
  76. pagercount_sql {
  77. SELECT hex(x) FROM t1
  78. }
  79. } [list 0 0 0 $blobcontent]
  80. # But if the other thread modifies the database, then the cache
  81. # must refill.
  82. #
  83. ifcapable mmap {
  84. set x [expr {[permutation]=="mmap" ? 1 : 6}]
  85. } else {
  86. set x 6
  87. }
  88. do_test pageropt-1.5 {
  89. db2 eval {CREATE TABLE t2(y)}
  90. pagercount_sql {
  91. SELECT hex(x) FROM t1
  92. }
  93. } [list $x 0 0 $blobcontent]
  94. do_test pageropt-1.6 {
  95. pagercount_sql {
  96. SELECT hex(x) FROM t1
  97. }
  98. } [list 0 0 0 $blobcontent]
  99. # Verify that the last page of an overflow chain is not read from
  100. # disk when deleting a row. The one row of t1(x) has four pages
  101. # of overflow. So deleting that row from t1 should involve reading
  102. # the sqlite_master table (1 page) the main page of t1 (1 page) and
  103. # the three overflow pages of t1 for a total of 5 pages.
  104. #
  105. # Pages written are page 1 (for the freelist pointer), the root page
  106. # of the table, and one of the overflow chain pointers because it
  107. # becomes the trunk of the freelist. Total 3.
  108. #
  109. do_test pageropt-2.1 {
  110. db close
  111. sqlite3 db test.db
  112. pagercount_sql {
  113. DELETE FROM t1 WHERE rowid=1
  114. }
  115. } {5 3 3}
  116. # When pulling pages off of the freelist, there is no reason
  117. # to actually bring in the old content.
  118. #
  119. do_test pageropt-2.2 {
  120. db close
  121. sqlite3 db test.db
  122. pagercount_sql {
  123. INSERT INTO t1 VALUES(randomblob(1500));
  124. }
  125. } {3 4 3}
  126. do_test pageropt-2.3 {
  127. pagercount_sql {
  128. INSERT INTO t1 VALUES(randomblob(1500));
  129. }
  130. } {0 4 3}
  131. # Note the new optimization that when pulling the very last page off of the
  132. # freelist we do not read the content of that page.
  133. #
  134. do_test pageropt-2.4 {
  135. pagercount_sql {
  136. INSERT INTO t1 VALUES(randomblob(1500));
  137. }
  138. } {0 5 3}
  139. # Appending a large quantity of data does not involve writing much
  140. # to the journal file.
  141. #
  142. do_test pageropt-3.1 {
  143. pagercount_sql {
  144. INSERT INTO t2 SELECT * FROM t1;
  145. }
  146. } {1 7 2}
  147. # Once again, we do not need to read the last page of an overflow chain
  148. # while deleting.
  149. #
  150. do_test pageropt-3.2 {
  151. pagercount_sql {
  152. DROP TABLE t2;
  153. }
  154. } {0 2 3}
  155. do_test pageropt-3.3 {
  156. pagercount_sql {
  157. DELETE FROM t1;
  158. }
  159. } {0 3 3}
  160. # There are now 11 pages on the freelist. Move them all into an
  161. # overflow chain by inserting a single large record. Starting from
  162. # a cold cache, only page 1, the root page of table t1, and the trunk
  163. # of the freelist need to be read (3 pages). And only those three
  164. # pages need to be journalled. But 13 pages need to be written:
  165. # page1, the root page of table t1, and an 11 page overflow chain.
  166. #
  167. do_test pageropt-4.1 {
  168. db close
  169. sqlite3 db test.db
  170. pagercount_sql {
  171. INSERT INTO t1 VALUES(randomblob(11300))
  172. }
  173. } {3 13 3}
  174. # Now we delete that big entries starting from a cold cache and an
  175. # empty freelist. The first 10 of the 11 pages overflow chain have
  176. # to be read, together with page1 and the root of the t1 table. 12
  177. # reads total. But only page1, the t1 root, and the trunk of the
  178. # freelist need to be journalled and written back.
  179. #
  180. do_test pageropt-4.2 {
  181. db close
  182. sqlite3 db test.db
  183. pagercount_sql {
  184. DELETE FROM t1
  185. }
  186. } {12 3 3}
  187. sqlite3_soft_heap_limit $cmdlinearg(soft-heap-limit)
  188. catch {db2 close}
  189. finish_test