1
0

vtab7.test 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. # 2006 July 25
  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. The focus
  12. # of this test is reading and writing to the database from within a
  13. # virtual table xSync() callback.
  14. #
  15. # $Id: vtab7.test,v 1.4 2007/12/04 16:54:53 drh Exp $
  16. set testdir [file dirname $argv0]
  17. source $testdir/tester.tcl
  18. ifcapable !vtab {
  19. finish_test
  20. return
  21. }
  22. # Register the echo module. Code inside the echo module appends elements
  23. # to the global tcl list variable ::echo_module whenever SQLite invokes
  24. # certain module callbacks. This includes the xSync(), xCommit() and
  25. # xRollback() callbacks. For each of these callback, two elements are
  26. # appended to ::echo_module, as follows:
  27. #
  28. # Module method Elements appended to ::echo_module
  29. # -------------------------------------------------------
  30. # xSync() xSync echo($tablename)
  31. # xCommit() xCommit echo($tablename)
  32. # xRollback() xRollback echo($tablename)
  33. # -------------------------------------------------------
  34. #
  35. # In each case, $tablename is replaced by the name of the real table (not
  36. # the echo table). By setting up a tcl trace on the ::echo_module variable,
  37. # code in this file arranges for a Tcl script to be executed from within
  38. # the echo module xSync() callback.
  39. #
  40. register_echo_module [sqlite3_connection_pointer db]
  41. trace add variable ::echo_module write echo_module_trace
  42. # This Tcl proc is invoked whenever the ::echo_module variable is written.
  43. #
  44. proc echo_module_trace {args} {
  45. # Filter out writes to ::echo_module that are not xSync, xCommit or
  46. # xRollback callbacks.
  47. if {[llength $::echo_module] < 2} return
  48. set x [lindex $::echo_module end-1]
  49. if {$x ne "xSync" && $x ne "xCommit" && $x ne "xRollback"} return
  50. regexp {^echo.(.*).$} [lindex $::echo_module end] dummy tablename
  51. # puts "Ladies and gentlemen, an $x on $tablename!"
  52. if {[info exists ::callbacks($x,$tablename)]} {
  53. eval $::callbacks($x,$tablename)
  54. }
  55. }
  56. # The following tests, vtab7-1.*, test that the trace callback on
  57. # ::echo_module is providing the expected tcl callbacks.
  58. do_test vtab7-1.1 {
  59. execsql {
  60. CREATE TABLE abc(a, b, c);
  61. CREATE VIRTUAL TABLE abc2 USING echo(abc);
  62. }
  63. } {}
  64. do_test vtab7-1.2 {
  65. set ::callbacks(xSync,abc) {incr ::counter}
  66. set ::counter 0
  67. execsql {
  68. INSERT INTO abc2 VALUES(1, 2, 3);
  69. }
  70. set ::counter
  71. } {1}
  72. # Write to an existing database table from within an xSync callback.
  73. do_test vtab7-2.1 {
  74. set ::callbacks(xSync,abc) {
  75. execsql {INSERT INTO log VALUES('xSync');}
  76. }
  77. execsql {
  78. CREATE TABLE log(msg);
  79. INSERT INTO abc2 VALUES(4, 5, 6);
  80. SELECT * FROM log;
  81. }
  82. } {xSync}
  83. do_test vtab7-2.3 {
  84. execsql {
  85. INSERT INTO abc2 VALUES(4, 5, 6);
  86. SELECT * FROM log;
  87. }
  88. } {xSync xSync}
  89. do_test vtab7-2.4 {
  90. execsql {
  91. INSERT INTO abc2 VALUES(4, 5, 6);
  92. SELECT * FROM log;
  93. }
  94. } {xSync xSync xSync}
  95. # Create a database table from within xSync callback.
  96. do_test vtab7-2.5 {
  97. set ::callbacks(xSync,abc) {
  98. execsql { CREATE TABLE newtab(d, e, f); }
  99. }
  100. execsql {
  101. INSERT INTO abc2 VALUES(1, 2, 3);
  102. SELECT name FROM sqlite_master ORDER BY name;
  103. }
  104. } {abc abc2 log newtab}
  105. # Drop a database table from within xSync callback.
  106. # This is not allowed. Tables cannot be dropped while
  107. # any other statement is active.
  108. #
  109. do_test vtab7-2.6 {
  110. set ::callbacks(xSync,abc) {
  111. set ::rc [catchsql { DROP TABLE newtab }]
  112. }
  113. execsql {
  114. INSERT INTO abc2 VALUES(1, 2, 3);
  115. SELECT name FROM sqlite_master ORDER BY name;
  116. }
  117. } {abc abc2 log newtab}
  118. do_test vtab7-2.6.1 {
  119. set ::rc
  120. } {1 {database table is locked}}
  121. execsql {DROP TABLE newtab}
  122. # Write to an attached database from xSync().
  123. ifcapable attach {
  124. do_test vtab7-3.1 {
  125. forcedelete test2.db
  126. forcedelete test2.db-journal
  127. execsql {
  128. ATTACH 'test2.db' AS db2;
  129. CREATE TABLE db2.stuff(description, shape, color);
  130. }
  131. set ::callbacks(xSync,abc) {
  132. execsql { INSERT INTO db2.stuff VALUES('abc', 'square', 'green'); }
  133. }
  134. execsql {
  135. INSERT INTO abc2 VALUES(1, 2, 3);
  136. SELECT * from stuff;
  137. }
  138. } {abc square green}
  139. }
  140. # UPDATE: The next test passes, but leaks memory. So leave it out.
  141. #
  142. # The following tests test that writing to the database from within
  143. # the xCommit callback causes a misuse error.
  144. # do_test vtab7-4.1 {
  145. # unset -nocomplain ::callbacks(xSync,abc)
  146. # set ::callbacks(xCommit,abc) {
  147. # execsql { INSERT INTO log VALUES('hello') }
  148. # }
  149. # catchsql {
  150. # INSERT INTO abc2 VALUES(1, 2, 3);
  151. # }
  152. # } {1 {library routine called out of sequence}}
  153. # These tests, vtab7-4.*, test that an SQLITE_LOCKED error is returned
  154. # if an attempt to write to a virtual module table or create a new
  155. # virtual table from within an xSync() callback.
  156. do_test vtab7-4.1 {
  157. execsql {
  158. CREATE TABLE def(d, e, f);
  159. CREATE VIRTUAL TABLE def2 USING echo(def);
  160. }
  161. set ::callbacks(xSync,abc) {
  162. set ::error [catchsql { INSERT INTO def2 VALUES(1, 2, 3) }]
  163. }
  164. execsql {
  165. INSERT INTO abc2 VALUES(1, 2, 3);
  166. }
  167. set ::error
  168. } {1 {database table is locked}}
  169. do_test vtab7-4.2 {
  170. set ::callbacks(xSync,abc) {
  171. set ::error [catchsql { CREATE VIRTUAL TABLE def3 USING echo(def) }]
  172. }
  173. execsql {
  174. INSERT INTO abc2 VALUES(1, 2, 3);
  175. }
  176. set ::error
  177. } {1 {database table is locked}}
  178. do_test vtab7-4.3 {
  179. set ::callbacks(xSync,abc) {
  180. set ::error [catchsql { DROP TABLE def2 }]
  181. }
  182. execsql {
  183. INSERT INTO abc2 VALUES(1, 2, 3);
  184. SELECT name FROM sqlite_master ORDER BY name;
  185. }
  186. set ::error
  187. } {1 {database table is locked}}
  188. trace remove variable ::echo_module write echo_module_trace
  189. unset -nocomplain ::callbacks
  190. finish_test