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