shared9.test 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. # 2012 October 5
  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. # The tests in this file are intended to show if two connections attach
  13. # to the same shared cache using different database names, views and
  14. # virtual tables may still be accessed.
  15. #
  16. set testdir [file dirname $argv0]
  17. source $testdir/tester.tcl
  18. source $testdir/lock_common.tcl
  19. set testprefix shared9
  20. ifcapable !view||!trigger {
  21. finish_test
  22. return
  23. }
  24. db close
  25. set enable_shared_cache [sqlite3_enable_shared_cache 1]
  26. sqlite3 db1 test.db
  27. sqlite3 db2 test.db
  28. forcedelete test.db2
  29. do_test 1.1 {
  30. db1 eval {
  31. ATTACH 'test.db2' AS 'fred';
  32. CREATE TABLE fred.t1(a, b, c);
  33. CREATE VIEW fred.v1 AS SELECT * FROM t1;
  34. CREATE TABLE fred.t2(a, b);
  35. CREATE TABLE fred.t3(a, b);
  36. CREATE TRIGGER fred.trig AFTER INSERT ON t2 BEGIN
  37. DELETE FROM t3;
  38. INSERT INTO t3 SELECT * FROM t2;
  39. END;
  40. INSERT INTO t2 VALUES(1, 2);
  41. SELECT * FROM t3;
  42. }
  43. } {1 2}
  44. do_test 1.2 { db2 eval "ATTACH 'test.db2' AS 'jones'" } {}
  45. do_test 1.3 { db2 eval "SELECT * FROM v1" } {}
  46. do_test 1.4 { db2 eval "INSERT INTO t2 VALUES(3, 4)" } {}
  47. ifcapable fts3 {
  48. do_test 1.5 {
  49. db1 eval {
  50. CREATE VIRTUAL TABLE fred.t4 USING fts4;
  51. INSERT INTO t4 VALUES('hello world');
  52. }
  53. } {}
  54. do_test 1.6 {
  55. db2 eval {
  56. INSERT INTO t4 VALUES('shared cache');
  57. SELECT * FROM t4 WHERE t4 MATCH 'hello';
  58. }
  59. } {{hello world}}
  60. do_test 1.7 {
  61. db1 eval {
  62. SELECT * FROM t4 WHERE t4 MATCH 'c*';
  63. }
  64. } {{shared cache}}
  65. }
  66. db1 close
  67. db2 close
  68. #-------------------------------------------------------------------------
  69. # The following tests attempt to find a similar problem with collation
  70. # sequence names - pointers to database handle specific allocations leaking
  71. # into schema objects and being used after the original handle has been
  72. # closed.
  73. #
  74. forcedelete test.db test.db2
  75. sqlite3 db1 test.db
  76. sqlite3 db2 test.db
  77. foreach x {collate1 collate2 collate3} {
  78. proc $x {a b} { string compare $a $b }
  79. db1 collate $x $x
  80. db2 collate $x $x
  81. }
  82. do_test 2.1 {
  83. db1 eval {
  84. CREATE TABLE t1(a, b, c COLLATE collate1);
  85. CREATE INDEX i1 ON t1(a COLLATE collate2, c, b);
  86. }
  87. } {}
  88. do_test 2.2 {
  89. db1 close
  90. db2 eval "INSERT INTO t1 VALUES('abc', 'def', 'ghi')"
  91. } {}
  92. db2 close
  93. #-------------------------------------------------------------------------
  94. # At one point, the following would cause a collation sequence belonging
  95. # to connection [db1] to be invoked by a call to [db2 eval]. Which is a
  96. # problem if [db1] has already been closed.
  97. #
  98. forcedelete test.db test.db2
  99. sqlite3 db1 test.db
  100. sqlite3 db2 test.db
  101. proc mycollate_db1 {a b} {set ::invoked_mycollate_db1 1 ; string compare $a $b}
  102. proc mycollate_db2 {a b} {string compare $a $b}
  103. db1 collate mycollate mycollate_db1
  104. db2 collate mycollate mycollate_db2
  105. do_test 2.3 {
  106. set ::invoked_mycollate_db1 0
  107. db1 eval {
  108. CREATE TABLE t1(a COLLATE mycollate, CHECK (a IN ('one', 'two', 'three')));
  109. INSERT INTO t1 VALUES('one');
  110. }
  111. db1 close
  112. set ::invoked_mycollate_db1
  113. } {1}
  114. do_test 2.4 {
  115. set ::invoked_mycollate_db1 0
  116. db2 eval {
  117. INSERT INTO t1 VALUES('two');
  118. }
  119. db2 close
  120. set ::invoked_mycollate_db1
  121. } {0}
  122. forcedelete test.db test.db2
  123. sqlite3 db1 test.db
  124. sqlite3 db2 test.db
  125. db1 collate mycollate mycollate_db1
  126. db2 collate mycollate mycollate_db2
  127. do_test 2.13 {
  128. set ::invoked_mycollate_db1 0
  129. db1 eval {
  130. CREATE TABLE t1(a, CHECK (a COLLATE mycollate IN ('one', 'two', 'three')));
  131. INSERT INTO t1 VALUES('one');
  132. }
  133. db1 close
  134. set ::invoked_mycollate_db1
  135. } {1}
  136. do_test 2.14 {
  137. set ::invoked_mycollate_db1 0
  138. db2 eval {
  139. INSERT INTO t1 VALUES('two');
  140. }
  141. db2 close
  142. set ::invoked_mycollate_db1
  143. } {0}
  144. #-------------------------------------------------------------------------
  145. # This test verifies that a bug causing a busy-handler belonging to one
  146. # shared-cache connection to be executed as a result of an sqlite3_step()
  147. # on another has been fixed.
  148. #
  149. forcedelete test.db test.db2
  150. sqlite3 db1 test.db
  151. sqlite3 db2 test.db
  152. proc busyhandler {handle args} {
  153. set ::busyhandler_invoked_for $handle
  154. return 1
  155. }
  156. db1 busy [list busyhandler db1]
  157. db2 busy [list busyhandler db2]
  158. do_test 3.1 {
  159. db1 eval {
  160. BEGIN;
  161. CREATE TABLE t1(a, b);
  162. CREATE TABLE t2(a, b);
  163. INSERT INTO t1 VALUES(1, 2);
  164. INSERT INTO t2 VALUES(1, 2);
  165. }
  166. # Keep this next COMMIT as a separate statement. This ensures that COMMIT
  167. # has already been compiled and loaded into the tcl interface statement
  168. # cache when it is attempted below.
  169. db1 eval COMMIT
  170. db1 eval {
  171. BEGIN;
  172. INSERT INTO t1 VALUES(3, 4);
  173. }
  174. } {}
  175. do_test 3.2 {
  176. set ::tf [launch_testfixture]
  177. testfixture $::tf {
  178. sqlite3 db test.db
  179. db eval {
  180. BEGIN;
  181. SELECT * FROM t1;
  182. }
  183. }
  184. } {1 2}
  185. do_test 3.3 {
  186. db2 eval { SELECT * FROM t2 }
  187. } {1 2}
  188. do_test 3.4 {
  189. list [catch { db1 eval COMMIT } msg] $msg
  190. } {1 {database is locked}}
  191. # At one point the following would fail, showing that the busy-handler
  192. # belonging to [db2] was invoked instead.
  193. do_test 3.5 {
  194. set ::busyhandler_invoked_for
  195. } {db1}
  196. do_test 3.6 {
  197. close $::tf
  198. db1 eval COMMIT
  199. } {}
  200. db1 close
  201. db2 close
  202. sqlite3_enable_shared_cache $::enable_shared_cache
  203. finish_test