rbu12.test 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. # 2015 February 16
  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. #
  12. source [file join [file dirname [info script]] rbu_common.tcl]
  13. if_no_rbu_support { finish_test ; return }
  14. source $testdir/lock_common.tcl
  15. set ::testprefix rbu12
  16. set setup_sql {
  17. DROP TABLE IF EXISTS xx;
  18. DROP TABLE IF EXISTS xy;
  19. CREATE TABLE xx(a, b, c PRIMARY KEY);
  20. INSERT INTO xx VALUES(1, 2, 3);
  21. CREATE TABLE xy(a, b, c PRIMARY KEY);
  22. ATTACH 'rbu.db' AS rbu;
  23. DROP TABLE IF EXISTS data_xx;
  24. CREATE TABLE rbu.data_xx(a, b, c, rbu_control);
  25. INSERT INTO data_xx VALUES(4, 5, 6, 0);
  26. INSERT INTO data_xx VALUES(7, 8, 9, 0);
  27. CREATE TABLE rbu.data_xy(a, b, c, rbu_control);
  28. INSERT INTO data_xy VALUES(10, 11, 12, 0);
  29. DETACH rbu;
  30. }
  31. do_multiclient_test tn {
  32. # Initialize a target (test.db) and rbu (rbu.db) database.
  33. #
  34. forcedelete rbu.db
  35. sql1 $setup_sql
  36. # Using connection 2, open a read transaction on the target database.
  37. # RBU will still be able to generate "test.db-oal", but it will not be
  38. # able to rename it to "test.db-wal".
  39. #
  40. do_test 1.$tn.1 {
  41. sql2 { BEGIN; SELECT * FROM xx; }
  42. } {1 2 3}
  43. do_test 1.$tn.2 {
  44. sqlite3rbu rbu test.db rbu.db
  45. while 1 {
  46. set res [rbu step]
  47. if {$res!="SQLITE_OK"} break
  48. }
  49. set res
  50. } {SQLITE_BUSY}
  51. do_test 1.$tn.3 { sql2 { SELECT * FROM xx; } } {1 2 3}
  52. do_test 1.$tn.4 { sql2 { SELECT * FROM xy; } } {}
  53. do_test 1.$tn.5 {
  54. list [file exists test.db-wal] [file exists test.db-oal]
  55. } {0 1}
  56. do_test 1.$tn.6 { sql2 COMMIT } {}
  57. # The rbu object that hit the SQLITE_BUSY error above cannot be reused.
  58. # It is stuck in a permanent SQLITE_BUSY state at this point.
  59. #
  60. do_test 1.$tn.7 { rbu step } {SQLITE_BUSY}
  61. do_test 1.$tn.8 {
  62. list [catch { rbu close } msg] $msg
  63. } {1 SQLITE_BUSY}
  64. do_test 1.$tn.9.1 { sql2 { BEGIN EXCLUSIVE } } {}
  65. do_test 1.$tn.9.2 {
  66. sqlite3rbu rbu test.db rbu.db
  67. rbu step
  68. } {SQLITE_BUSY}
  69. do_test 1.$tn.9.3 {
  70. list [catch { rbu close } msg] $msg
  71. } {1 {SQLITE_BUSY - database is locked}}
  72. do_test 1.$tn.9.4 { sql2 COMMIT } {}
  73. sqlite3rbu rbu test.db rbu.db
  74. do_test 1.$tn.10.1 { sql2 { BEGIN EXCLUSIVE } } {}
  75. do_test 1.$tn.10.2 {
  76. rbu step
  77. } {SQLITE_BUSY}
  78. do_test 1.$tn.10.3 {
  79. list [catch { rbu close } msg] $msg
  80. } {1 SQLITE_BUSY}
  81. do_test 1.$tn.10.4 { sql2 COMMIT } {}
  82. # A new rbu object can finish the work though.
  83. #
  84. do_test 1.$tn.11 {
  85. sqlite3rbu rbu test.db rbu.db
  86. rbu step
  87. } {SQLITE_OK}
  88. do_test 1.$tn.12 {
  89. list [file exists test.db-wal] [file exists test.db-oal]
  90. } {1 0}
  91. do_test 1.$tn.13 {
  92. while 1 {
  93. set res [rbu step]
  94. if {$res!="SQLITE_OK"} break
  95. }
  96. set res
  97. } {SQLITE_DONE}
  98. do_test 1.$tn.14 {
  99. rbu close
  100. } {SQLITE_DONE}
  101. }
  102. do_multiclient_test tn {
  103. # Initialize a target (test.db) and rbu (rbu.db) database.
  104. #
  105. forcedelete rbu.db
  106. sql1 $setup_sql
  107. do_test 2.$tn.1 {
  108. sqlite3rbu rbu test.db rbu.db
  109. while {[file exists test.db-wal]==0} {
  110. if {[rbu step]!="SQLITE_OK"} {error "problem here...."}
  111. }
  112. rbu close
  113. } {SQLITE_OK}
  114. do_test 2.$tn.2 { sql2 { BEGIN IMMEDIATE } } {}
  115. do_test 2.$tn.3 {
  116. sqlite3rbu rbu test.db rbu.db
  117. rbu step
  118. } {SQLITE_BUSY}
  119. do_test 2.$tn.4 { list [catch { rbu close } msg] $msg } {1 SQLITE_BUSY}
  120. do_test 2.$tn.5 {
  121. sql2 { SELECT * FROM xx ; COMMIT }
  122. } {1 2 3 4 5 6 7 8 9}
  123. do_test 2.$tn.6 {
  124. sqlite3rbu rbu test.db rbu.db
  125. rbu step
  126. rbu close
  127. } {SQLITE_OK}
  128. do_test 2.$tn.7 { sql2 { BEGIN EXCLUSIVE } } {}
  129. do_test 2.$tn.8 {
  130. sqlite3rbu rbu test.db rbu.db
  131. rbu step
  132. } {SQLITE_BUSY}
  133. do_test 2.$tn.9 { list [catch { rbu close } msg] $msg } {1 SQLITE_BUSY}
  134. do_test 2.$tn.10 {
  135. sql2 { SELECT * FROM xx ; COMMIT }
  136. } {1 2 3 4 5 6 7 8 9}
  137. do_test 2.$tn.11 {
  138. sqlite3rbu rbu test.db rbu.db
  139. while {[rbu step]=="SQLITE_OK"} {}
  140. rbu close
  141. } {SQLITE_DONE}
  142. }
  143. #-------------------------------------------------------------------------
  144. # Test that "PRAGMA data_version" works when an RBU client writes the
  145. # database.
  146. #
  147. do_multiclient_test tn {
  148. # Initialize a target (test.db) and rbu (rbu.db) database.
  149. #
  150. forcedelete rbu.db
  151. sql1 $setup_sql
  152. # Check the initial database contains table "xx" with a single row.
  153. # Also save the current values of "PRAGMA data-version" for [db1]
  154. # and [db2].
  155. #
  156. do_test 2.$tn.1 {
  157. list [sql1 { SELECT count(*) FROM xx }] [sql2 { SELECT count(*) FROM xx }]
  158. } {1 1}
  159. set V1 [sql1 {PRAGMA data_version}]
  160. set V2 [sql2 {PRAGMA data_version}]
  161. # Check the values of data-version have not magically changed.
  162. #
  163. do_test 2.$tn.2 {
  164. list [sql1 {PRAGMA data_version}] [sql2 {PRAGMA data_version}]
  165. } [list $V1 $V2]
  166. # Start stepping the RBU. From the point of view of [db1] and [db2], the
  167. # data-version values remain unchanged until the database contents are
  168. # modified. At which point the values are incremented.
  169. #
  170. sqlite3rbu rbu test.db rbu.db
  171. set x 0
  172. while {[db one {SELECT count(*) FROM xx}]==1} {
  173. do_test 2.$tn.3.[incr x] {
  174. list [sql1 {PRAGMA data_version}] [sql2 {PRAGMA data_version}]
  175. } [list $V1 $V2]
  176. rbu step
  177. }
  178. do_test 2.$tn.5.1 { expr {$V1 < [sql1 {PRAGMA data_version}]} } 1
  179. do_test 2.$tn.5.2 { expr {$V2 < [sql2 {PRAGMA data_version}]} } 1
  180. # Check the db contents is as expected.
  181. #
  182. do_test 2.$tn.4 {
  183. list [sql1 {SELECT count(*) FROM xx}] [sql2 {SELECT count(*) FROM xx}]
  184. } {3 3}
  185. set V1 [sql1 {PRAGMA data_version}]
  186. set V2 [sql2 {PRAGMA data_version}]
  187. # Finish applying the RBU (i.e. do the incremental checkpoint). Check that
  188. # this does not cause the data-version values to change.
  189. #
  190. while {[rbu step]=="SQLITE_OK"} { }
  191. rbu close
  192. do_test 2.$tn.6 {
  193. list [sql1 {PRAGMA data_version}] [sql2 {PRAGMA data_version}]
  194. } [list $V1 $V2]
  195. }
  196. finish_test