xref: /sqlite-3.40.0/ext/rtree/rtree8.test (revision b80bb6ce)
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}
104do_execsql_test rtree8-2.1.2 { DELETE FROM t1_node } {}
105for {set i 1} {$i <= 50} {incr i} {
106  do_catchsql_test rtree8-2.1.3.$i {
107    SELECT * FROM t1 WHERE id = $i
108  } {1 {database disk image is malformed}}
109}
110do_catchsql_test rtree8-2.1.4 {
111  SELECT * FROM t1
112} {1 {database disk image is malformed}}
113do_catchsql_test rtree8-2.1.5 {
114  DELETE FROM t1
115} {1 {database disk image is malformed}}
116
117do_execsql_test rtree8-2.1.6 {
118  DROP TABLE t1;
119  CREATE VIRTUAL TABLE t1 USING rtree_i32(id, x1, x2);
120} {}
121
122
123populate_t1 50
124do_execsql_test rtree8-2.2.1 {
125  DELETE FROM t1_parent
126} {}
127do_catchsql_test rtree8-2.2.2 {
128  DELETE FROM t1 WHERE id=25
129} {1 {database disk image is malformed}}
130do_execsql_test rtree8-2.2.3 {
131  DROP TABLE t1;
132  CREATE VIRTUAL TABLE t1 USING rtree_i32(id, x1, x2);
133} {}
134
135
136#-------------------------------------------------------------------------
137# Test that trying to use the MATCH operator with the r-tree module does
138# not confuse it.
139#
140populate_t1 10
141do_catchsql_test rtree8-3.1 {
142  SELECT * FROM t1 WHERE x1 MATCH '1234'
143} {1 {SQL logic error}}
144
145#-------------------------------------------------------------------------
146# Test a couple of invalid arguments to rtreedepth().
147#
148do_catchsql_test rtree8-4.1 {
149  SELECT rtreedepth('hello world')
150} {1 {Invalid argument to rtreedepth()}}
151do_catchsql_test rtree8-4.2 {
152  SELECT rtreedepth(X'00')
153} {1 {Invalid argument to rtreedepth()}}
154
155
156#-------------------------------------------------------------------------
157# Delete half of a lopsided tree.
158#
159do_execsql_test rtree8-5.1 {
160  CREATE VIRTUAL TABLE t2 USING rtree_i32(id, x1, x2)
161} {}
162do_test rtree8-5.2 {
163  execsql BEGIN
164  for {set i 0} {$i < 100} {incr i} {
165    execsql { INSERT INTO t2 VALUES($i, 100, 101) }
166  }
167  for {set i 100} {$i < 200} {incr i} {
168    execsql { INSERT INTO t2 VALUES($i, 1000, 1001) }
169  }
170  execsql COMMIT
171} {}
172do_rtree_integrity_test rtree8-5.3 t2
173do_test rtree8-5.4 {
174  execsql BEGIN
175  for {set i 0} {$i < 200} {incr i} {
176    execsql { DELETE FROM t2 WHERE id = $i }
177  }
178  execsql COMMIT
179} {}
180do_rtree_integrity_test rtree8-5.5 t2
181
182# 2018-05-24
183# The following script caused an assertion fault and/or segfault
184# prior to the fix that prevents simultaneous reads and writes on
185# the same rtree virtual table.
186#
187do_test rtree8-6.1 {
188  db close
189  sqlite3 db :memory:
190  db eval {
191    PRAGMA page_size=512;
192    CREATE VIRTUAL TABLE t1 USING rtree(id,x1,x2,y1,y2);
193    WITH RECURSIVE c(x) AS (VALUES(0) UNION ALL SELECT x+1 FROM c WHERE x<49)
194    INSERT INTO t1 SELECT x, x, x+1, x, x+1 FROM c;
195  }
196  set rc [catch {
197    db eval {SELECT id FROM t1} x {
198      db eval {DELETE FROM t1 WHERE id=$x(id)}
199    }
200  } msg]
201  lappend rc $msg
202} {1 {database table is locked}}
203
204
205
206
207finish_test
208