rtree8.test 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. # 2010 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. #
  13. if {![info exists testdir]} {
  14. set testdir [file join [file dirname [info script]] .. .. test]
  15. }
  16. source [file join [file dirname [info script]] rtree_util.tcl]
  17. source $testdir/tester.tcl
  18. ifcapable !rtree { finish_test ; return }
  19. #-------------------------------------------------------------------------
  20. # The following block of tests - rtree8-1.* - feature reading and writing
  21. # an r-tree table while there exist open cursors on it.
  22. #
  23. proc populate_t1 {n} {
  24. execsql { DELETE FROM t1 }
  25. for {set i 1} {$i <= $n} {incr i} {
  26. execsql { INSERT INTO t1 VALUES($i, $i, $i+2) }
  27. }
  28. }
  29. # A DELETE while a cursor is reading the table.
  30. #
  31. do_test rtree8-1.1.1 {
  32. execsql { PRAGMA page_size = 512 }
  33. execsql { CREATE VIRTUAL TABLE t1 USING rtree_i32(id, x1, x2) }
  34. populate_t1 5
  35. } {}
  36. do_test rtree8-1.1.2 {
  37. set res [list]
  38. set rc [catch {
  39. db eval { SELECT * FROM t1 } {
  40. lappend res $x1 $x2
  41. if {$id==3} { db eval { DELETE FROM t1 WHERE id>3 } }
  42. }
  43. } msg];
  44. lappend rc $msg
  45. set rc
  46. } {1 {database table is locked}}
  47. do_test rtree8-1.1.2b {
  48. db eval { SELECT * FROM t1 ORDER BY +id } {
  49. if {$id==3} { db eval { DELETE FROM t1 WHERE id>3 } }
  50. }
  51. db eval {SELECT x1, x2 FROM t1}
  52. } {1 3 2 4 3 5}
  53. do_test rtree8-1.1.3 {
  54. execsql { SELECT * FROM t1 }
  55. } {1 1 3 2 2 4 3 3 5}
  56. # Many SELECTs on the same small table.
  57. #
  58. proc nested_select {n} {
  59. set ::max $n
  60. db eval { SELECT * FROM t1 } {
  61. if {$id == $n} { nested_select [expr $n+1] }
  62. }
  63. return $::max
  64. }
  65. do_test rtree8-1.2.1 { populate_t1 50 } {}
  66. do_test rtree8-1.2.2 { nested_select 1 } {51}
  67. # This test runs many SELECT queries simultaneously against a large
  68. # table, causing a collision in the hash-table used to store r-tree
  69. # nodes internally.
  70. #
  71. populate_t1 1500
  72. do_rtree_integrity_test rtree8-1.3.0 t1
  73. do_execsql_test rtree8-1.3.1 { SELECT max(nodeno) FROM t1_node } {183}
  74. do_test rtree8-1.3.2 {
  75. set rowids [execsql {SELECT min(rowid) FROM t1_rowid GROUP BY nodeno}]
  76. set stmt_list [list]
  77. foreach row $rowids {
  78. set stmt [sqlite3_prepare db "SELECT * FROM t1 WHERE id = $row" -1 tail]
  79. sqlite3_step $stmt
  80. lappend res_list [sqlite3_column_int $stmt 0]
  81. lappend stmt_list $stmt
  82. }
  83. } {}
  84. do_test rtree8-1.3.3 { set res_list } $rowids
  85. do_execsql_test rtree8-1.3.4 { SELECT count(*) FROM t1 } {1500}
  86. do_test rtree8-1.3.5 {
  87. foreach stmt $stmt_list { sqlite3_finalize $stmt }
  88. } {}
  89. #-------------------------------------------------------------------------
  90. # The following block of tests - rtree8-2.* - test a couple of database
  91. # corruption cases. In this case things are not corrupted at the b-tree
  92. # level, but the contents of the various tables used internally by an
  93. # r-tree table are inconsistent.
  94. #
  95. populate_t1 50
  96. do_execsql_test rtree8-2.1.1 { SELECT max(nodeno) FROM t1_node } {5}
  97. sqlite3_db_config db DEFENSIVE 0
  98. do_execsql_test rtree8-2.1.2 { DELETE FROM t1_node } {}
  99. for {set i 1} {$i <= 50} {incr i} {
  100. do_catchsql_test rtree8-2.1.3.$i {
  101. SELECT * FROM t1 WHERE id = $i
  102. } {1 {database disk image is malformed}}
  103. }
  104. do_catchsql_test rtree8-2.1.4 {
  105. SELECT * FROM t1
  106. } {1 {database disk image is malformed}}
  107. do_catchsql_test rtree8-2.1.5 {
  108. DELETE FROM t1
  109. } {1 {database disk image is malformed}}
  110. do_execsql_test rtree8-2.1.6 {
  111. DROP TABLE t1;
  112. CREATE VIRTUAL TABLE t1 USING rtree_i32(id, x1, x2);
  113. } {}
  114. populate_t1 50
  115. sqlite3_db_config db DEFENSIVE 0
  116. do_execsql_test rtree8-2.2.1 {
  117. DELETE FROM t1_parent
  118. } {}
  119. do_catchsql_test rtree8-2.2.2 {
  120. DELETE FROM t1 WHERE id=25
  121. } {1 {database disk image is malformed}}
  122. do_execsql_test rtree8-2.2.3 {
  123. DROP TABLE t1;
  124. CREATE VIRTUAL TABLE t1 USING rtree_i32(id, x1, x2);
  125. } {}
  126. #-------------------------------------------------------------------------
  127. # Test that trying to use the MATCH operator with the r-tree module does
  128. # not confuse it.
  129. #
  130. populate_t1 10
  131. do_catchsql_test rtree8-3.1 {
  132. SELECT * FROM t1 WHERE x1 MATCH '1234'
  133. } {1 {SQL logic error}}
  134. #-------------------------------------------------------------------------
  135. # Test a couple of invalid arguments to rtreedepth().
  136. #
  137. do_catchsql_test rtree8-4.1 {
  138. SELECT rtreedepth('hello world')
  139. } {1 {Invalid argument to rtreedepth()}}
  140. do_catchsql_test rtree8-4.2 {
  141. SELECT rtreedepth(X'00')
  142. } {1 {Invalid argument to rtreedepth()}}
  143. #-------------------------------------------------------------------------
  144. # Delete half of a lopsided tree.
  145. #
  146. do_execsql_test rtree8-5.1 {
  147. CREATE VIRTUAL TABLE t2 USING rtree_i32(id, x1, x2)
  148. } {}
  149. do_test rtree8-5.2 {
  150. execsql BEGIN
  151. for {set i 0} {$i < 100} {incr i} {
  152. execsql { INSERT INTO t2 VALUES($i, 100, 101) }
  153. }
  154. for {set i 100} {$i < 200} {incr i} {
  155. execsql { INSERT INTO t2 VALUES($i, 1000, 1001) }
  156. }
  157. execsql COMMIT
  158. } {}
  159. do_rtree_integrity_test rtree8-5.3 t2
  160. do_test rtree8-5.4 {
  161. execsql BEGIN
  162. for {set i 0} {$i < 200} {incr i} {
  163. execsql { DELETE FROM t2 WHERE id = $i }
  164. }
  165. execsql COMMIT
  166. } {}
  167. do_rtree_integrity_test rtree8-5.5 t2
  168. # 2018-05-24
  169. # The following script caused an assertion fault and/or segfault
  170. # prior to the fix that prevents simultaneous reads and writes on
  171. # the same rtree virtual table.
  172. #
  173. do_test rtree8-6.1 {
  174. db close
  175. sqlite3 db :memory:
  176. db eval {
  177. PRAGMA page_size=512;
  178. CREATE VIRTUAL TABLE t1 USING rtree(id,x1,x2,y1,y2);
  179. WITH RECURSIVE c(x) AS (VALUES(0) UNION ALL SELECT x+1 FROM c WHERE x<49)
  180. INSERT INTO t1 SELECT x, x, x+1, x, x+1 FROM c;
  181. }
  182. set rc [catch {
  183. db eval {SELECT id FROM t1} x {
  184. db eval {DELETE FROM t1 WHERE id=$x(id)}
  185. }
  186. } msg]
  187. lappend rc $msg
  188. } {1 {database table is locked}}
  189. finish_test