• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# 2008 Feb 19
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 focus of this file is testing the r-tree extension.
13#
14
15if {![info exists testdir]} {
16  set testdir [file join [file dirname [info script]] .. .. test]
17}
18source [file join [file dirname [info script]] rtree_util.tcl]
19source $testdir/tester.tcl
20
21# Test plan:
22#
23#   rtree-1.*: Creating/destroying r-tree tables.
24#   rtree-2.*: Test the implicit constraints - unique rowid and
25#              (coord[N]<=coord[N+1]) for even values of N. Also
26#              automatic assigning of rowid values.
27#   rtree-3.*: Linear scans of r-tree data.
28#   rtree-4.*: Test INSERT
29#   rtree-5.*: Test DELETE
30#   rtree-6.*: Test UPDATE
31#   rtree-7.*: Test renaming an r-tree table.
32#   rtree-8.*: Test constrained scans of r-tree data.
33#
34
35ifcapable !rtree {
36  finish_test
37  return
38}
39
40#----------------------------------------------------------------------------
41# Test cases rtree-1.* test CREATE and DROP table statements.
42#
43
44# Test creating and dropping an rtree table.
45#
46do_test rtree-1.1.1 {
47  execsql { CREATE VIRTUAL TABLE t1 USING rtree(ii, x1, x2, y1, y2) }
48} {}
49do_test rtree-1.1.2 {
50  execsql { SELECT name FROM sqlite_master ORDER BY name }
51} {t1 t1_node t1_parent t1_rowid}
52do_test rtree-1.1.3 {
53  execsql {
54    DROP TABLE t1;
55    SELECT name FROM sqlite_master ORDER BY name;
56  }
57} {}
58
59# Test creating and dropping an rtree table with an odd name in
60# an attached database.
61#
62do_test rtree-1.2.1 {
63  file delete -force test2.db
64  execsql {
65    ATTACH 'test2.db' AS aux;
66    CREATE VIRTUAL TABLE aux.'a" "b' USING rtree(ii, x1, x2, y1, y2);
67  }
68} {}
69do_test rtree-1.2.2 {
70  execsql { SELECT name FROM sqlite_master ORDER BY name }
71} {}
72do_test rtree-1.2.3 {
73  execsql { SELECT name FROM aux.sqlite_master ORDER BY name }
74} {{a" "b} {a" "b_node} {a" "b_parent} {a" "b_rowid}}
75do_test rtree-1.2.4 {
76  execsql {
77    DROP TABLE aux.'a" "b';
78    SELECT name FROM aux.sqlite_master ORDER BY name;
79  }
80} {}
81
82# Test that the logic for checking the number of columns specified
83# for an rtree table. Acceptable values are odd numbers between 3 and
84# 11, inclusive.
85#
86set cols [list i1 i2 i3 i4 i5 i6 i7 i8 i9 iA iB iC iD iE iF iG iH iI iJ iK]
87for {set nCol 1} {$nCol<[llength $cols]} {incr nCol} {
88
89  set columns [join [lrange $cols 0 [expr {$nCol-1}]] ,]
90
91  set X {0 {}}
92  if {$nCol%2 == 0}  { set X {1 {Wrong number of columns for an rtree table}} }
93  if {$nCol < 3}     { set X {1 {Too few columns for an rtree table}} }
94  if {$nCol > 11}    { set X {1 {Too many columns for an rtree table}} }
95
96  do_test rtree-1.3.$nCol {
97    catchsql "
98      CREATE VIRTUAL TABLE t1 USING rtree($columns);
99    "
100  } $X
101
102  catchsql { DROP TABLE t1 }
103}
104
105# Test that it is possible to open an existing database that contains
106# r-tree tables.
107#
108do_test rtree-1.4.1 {
109  execsql {
110    CREATE VIRTUAL TABLE t1 USING rtree(ii, x1, x2);
111    INSERT INTO t1 VALUES(1, 5.0, 10.0);
112    INSERT INTO t1 VALUES(2, 15.0, 20.0);
113  }
114} {}
115do_test rtree-1.4.2 {
116  db close
117  sqlite3 db test.db
118  execsql { SELECT * FROM t1 ORDER BY ii }
119} {1 5.0 10.0 2 15.0 20.0}
120do_test rtree-1.4.3 {
121  execsql { DROP TABLE t1 }
122} {}
123
124# Test that it is possible to create an r-tree table with ridiculous
125# column names.
126#
127do_test rtree-1.5.1 {
128  execsql {
129    CREATE VIRTUAL TABLE t1 USING rtree("the key", "x dim.", "x2'dim");
130    INSERT INTO t1 VALUES(1, 2, 3);
131    SELECT "the key", "x dim.", "x2'dim" FROM t1;
132  }
133} {1 2.0 3.0}
134do_test rtree-1.5.1 {
135  execsql { DROP TABLE t1 }
136} {}
137
138# Force the r-tree constructor to fail.
139#
140do_test rtree-1.6.1 {
141  execsql { CREATE TABLE t1_rowid(a); }
142  catchsql {
143    CREATE VIRTUAL TABLE t1 USING rtree("the key", "x dim.", "x2'dim");
144  }
145} {1 {table "t1_rowid" already exists}}
146do_test rtree-1.6.1 {
147  execsql { DROP TABLE t1_rowid }
148} {}
149
150#----------------------------------------------------------------------------
151# Test cases rtree-2.*
152#
153do_test rtree-2.1.1 {
154  execsql {
155    CREATE VIRTUAL TABLE t1 USING rtree(ii, x1, x2, y1, y2);
156    SELECT * FROM t1;
157  }
158} {}
159
160do_test rtree-2.1.2 {
161  execsql { INSERT INTO t1 VALUES(NULL, 1, 3, 2, 4) }
162  execsql { SELECT * FROM t1 }
163} {1 1.0 3.0 2.0 4.0}
164do_test rtree-2.1.3 {
165  execsql { INSERT INTO t1 VALUES(NULL, 1, 3, 2, 4) }
166  execsql { SELECT rowid FROM t1 ORDER BY rowid }
167} {1 2}
168do_test rtree-2.1.3 {
169  execsql { INSERT INTO t1 VALUES(NULL, 1, 3, 2, 4) }
170  execsql { SELECT ii FROM t1 ORDER BY ii }
171} {1 2 3}
172
173do_test rtree-2.2.1 {
174  catchsql { INSERT INTO t1 VALUES(2, 1, 3, 2, 4) }
175} {1 {constraint failed}}
176do_test rtree-2.2.2 {
177  catchsql { INSERT INTO t1 VALUES(4, 1, 3, 4, 2) }
178} {1 {constraint failed}}
179do_test rtree-2.2.3 {
180  catchsql { INSERT INTO t1 VALUES(4, 3, 1, 2, 4) }
181} {1 {constraint failed}}
182do_test rtree-2.2.4 {
183  execsql { SELECT ii FROM t1 ORDER BY ii }
184} {1 2 3}
185
186do_test rtree-2.X {
187  execsql { DROP TABLE t1 }
188} {}
189
190#----------------------------------------------------------------------------
191# Test cases rtree-3.* test linear scans of r-tree table data. To test
192# this we have to insert some data into an r-tree, but that is not the
193# focus of these tests.
194#
195do_test rtree-3.1.1 {
196  execsql {
197    CREATE VIRTUAL TABLE t1 USING rtree(ii, x1, x2, y1, y2);
198    SELECT * FROM t1;
199  }
200} {}
201do_test rtree-3.1.2 {
202  execsql {
203    INSERT INTO t1 VALUES(5, 1, 3, 2, 4);
204    SELECT * FROM t1;
205  }
206} {5 1.0 3.0 2.0 4.0}
207do_test rtree-3.1.3 {
208  execsql {
209    INSERT INTO t1 VALUES(6, 2, 6, 4, 8);
210    SELECT * FROM t1;
211  }
212} {5 1.0 3.0 2.0 4.0 6 2.0 6.0 4.0 8.0}
213
214# Test the constraint on the coordinates (c[i]<=c[i+1] where (i%2==0)):
215do_test rtree-3.2.1 {
216  catchsql { INSERT INTO t1 VALUES(7, 2, 6, 4, 3) }
217} {1 {constraint failed}}
218do_test rtree-3.2.2 {
219  catchsql { INSERT INTO t1 VALUES(8, 2, 6, 3, 3) }
220} {0 {}}
221
222#----------------------------------------------------------------------------
223# Test cases rtree-5.* test DELETE operations.
224#
225do_test rtree-5.1.1 {
226  execsql { CREATE VIRTUAL TABLE t2 USING rtree(ii, x1, x2) }
227} {}
228do_test rtree-5.1.2 {
229  execsql {
230    INSERT INTO t2 VALUES(1, 10, 20);
231    INSERT INTO t2 VALUES(2, 30, 40);
232    INSERT INTO t2 VALUES(3, 50, 60);
233    SELECT * FROM t2 ORDER BY ii;
234  }
235} {1 10.0 20.0 2 30.0 40.0 3 50.0 60.0}
236do_test rtree-5.1.3 {
237  execsql {
238    DELETE FROM t2 WHERE ii=2;
239    SELECT * FROM t2 ORDER BY ii;
240  }
241} {1 10.0 20.0 3 50.0 60.0}
242do_test rtree-5.1.4 {
243  execsql {
244    DELETE FROM t2 WHERE ii=1;
245    SELECT * FROM t2 ORDER BY ii;
246  }
247} {3 50.0 60.0}
248do_test rtree-5.1.5 {
249  execsql {
250    DELETE FROM t2 WHERE ii=3;
251    SELECT * FROM t2 ORDER BY ii;
252  }
253} {}
254do_test rtree-5.1.6 {
255  execsql { SELECT * FROM t2_rowid }
256} {}
257
258#----------------------------------------------------------------------------
259# Test cases rtree-5.* test UPDATE operations.
260#
261do_test rtree-6.1.1 {
262  execsql { CREATE VIRTUAL TABLE t3 USING rtree(ii, x1, x2, y1, y2) }
263} {}
264do_test rtree-6.1.2 {
265  execsql {
266    INSERT INTO t3 VALUES(1, 2, 3, 4, 5);
267    UPDATE t3 SET x2=5;
268    SELECT * FROM t3;
269  }
270} {1 2.0 5.0 4.0 5.0}
271do_test rtree-6.1.3 {
272  execsql { UPDATE t3 SET ii = 2 }
273  execsql { SELECT * FROM t3 }
274} {2 2.0 5.0 4.0 5.0}
275
276#----------------------------------------------------------------------------
277# Test cases rtree-7.* test rename operations.
278#
279do_test rtree-7.1.1 {
280  execsql {
281    CREATE VIRTUAL TABLE t4 USING rtree(ii, x1, x2, y1, y2, z1, z2);
282    INSERT INTO t4 VALUES(1, 2, 3, 4, 5, 6, 7);
283  }
284} {}
285do_test rtree-7.1.2 {
286  execsql { ALTER TABLE t4 RENAME TO t5 }
287  execsql { SELECT * FROM t5 }
288} {1 2.0 3.0 4.0 5.0 6.0 7.0}
289do_test rtree-7.1.3 {
290  db close
291  sqlite3 db test.db
292  execsql { SELECT * FROM t5 }
293} {1 2.0 3.0 4.0 5.0 6.0 7.0}
294do_test rtree-7.1.4 {
295  execsql { ALTER TABLE t5 RENAME TO 'raisara "one"'''}
296  execsql { SELECT * FROM "raisara ""one""'" }
297} {1 2.0 3.0 4.0 5.0 6.0 7.0}
298do_test rtree-7.1.5 {
299  execsql { SELECT * FROM 'raisara "one"''' }
300} {1 2.0 3.0 4.0 5.0 6.0 7.0}
301do_test rtree-7.1.6 {
302  execsql { ALTER TABLE "raisara ""one""'" RENAME TO "abc 123" }
303  execsql { SELECT * FROM "abc 123" }
304} {1 2.0 3.0 4.0 5.0 6.0 7.0}
305do_test rtree-7.1.7 {
306  db close
307  sqlite3 db test.db
308  execsql { SELECT * FROM "abc 123" }
309} {1 2.0 3.0 4.0 5.0 6.0 7.0}
310
311# An error midway through a rename operation.
312do_test rtree-7.2.1 {
313  execsql {
314    CREATE TABLE t4_node(a);
315  }
316  catchsql { ALTER TABLE "abc 123" RENAME TO t4 }
317} {1 {SQL logic error or missing database}}
318do_test rtree-7.2.2 {
319  execsql { SELECT * FROM "abc 123" }
320} {1 2.0 3.0 4.0 5.0 6.0 7.0}
321do_test rtree-7.2.3 {
322  execsql {
323    DROP TABLE t4_node;
324    CREATE TABLE t4_rowid(a);
325  }
326  catchsql { ALTER TABLE "abc 123" RENAME TO t4 }
327} {1 {SQL logic error or missing database}}
328do_test rtree-7.2.4 {
329  db close
330  sqlite3 db test.db
331  execsql { SELECT * FROM "abc 123" }
332} {1 2.0 3.0 4.0 5.0 6.0 7.0}
333do_test rtree-7.2.5 {
334  execsql { DROP TABLE t4_rowid }
335  execsql { ALTER TABLE "abc 123" RENAME TO t4 }
336  execsql { SELECT * FROM t4 }
337} {1 2.0 3.0 4.0 5.0 6.0 7.0}
338
339
340#----------------------------------------------------------------------------
341# Test cases rtree-8.*
342#
343
344# Test that the function to determine if a leaf cell is part of the
345# result set works.
346do_test rtree-8.1.1 {
347  execsql {
348    CREATE VIRTUAL TABLE t6 USING rtree(ii, x1, x2);
349    INSERT INTO t6 VALUES(1, 3, 7);
350    INSERT INTO t6 VALUES(2, 4, 6);
351  }
352} {}
353do_test rtree-8.1.2 { execsql { SELECT ii FROM t6 WHERE x1>2 } } {1 2}
354do_test rtree-8.1.3 { execsql { SELECT ii FROM t6 WHERE x1>3 } } {2}
355do_test rtree-8.1.4 { execsql { SELECT ii FROM t6 WHERE x1>4 } } {}
356do_test rtree-8.1.5 { execsql { SELECT ii FROM t6 WHERE x1>5 } } {}
357do_test rtree-8.1.6 { execsql { SELECT ii FROM t6 WHERE x1<3 } } {}
358do_test rtree-8.1.7 { execsql { SELECT ii FROM t6 WHERE x1<4 } } {1}
359do_test rtree-8.1.8 { execsql { SELECT ii FROM t6 WHERE x1<5 } } {1 2}
360
361#----------------------------------------------------------------------------
362# Test cases rtree-9.*
363#
364# Test that ticket #3549 is fixed.
365do_test rtree-9.1 {
366  execsql {
367    CREATE TABLE foo (id INTEGER PRIMARY KEY);
368    CREATE VIRTUAL TABLE bar USING rtree (id, minX, maxX, minY, maxY);
369    INSERT INTO foo VALUES (null);
370    INSERT INTO foo SELECT null FROM foo;
371    INSERT INTO foo SELECT null FROM foo;
372    INSERT INTO foo SELECT null FROM foo;
373    INSERT INTO foo SELECT null FROM foo;
374    INSERT INTO foo SELECT null FROM foo;
375    INSERT INTO foo SELECT null FROM foo;
376    DELETE FROM foo WHERE id > 40;
377    INSERT INTO bar SELECT NULL, 0, 0, 0, 0 FROM foo;
378  }
379} {}
380
381# This used to crash.
382do_test rtree-9.2 {
383  execsql {
384    SELECT count(*) FROM bar b1, bar b2, foo s1 WHERE s1.id = b1.id;
385  }
386} {1600}
387do_test rtree-9.3 {
388  execsql {
389    SELECT count(*) FROM bar b1, bar b2, foo s1
390    WHERE b1.minX <= b2.maxX AND s1.id = b1.id;
391  }
392} {1600}
393
394#-------------------------------------------------------------------------
395# Ticket #3970: Check that the error message is meaningful when a
396# keyword is used as a column name.
397#
398do_test rtree-10.1 {
399  catchsql { CREATE VIRTUAL TABLE t7 USING rtree(index, x1, y1, x2, y2) }
400} {1 {near "index": syntax error}}
401
402#-------------------------------------------------------------------------
403# Test last_insert_rowid().
404#
405do_test rtree-11.1 {
406  execsql {
407    CREATE VIRTUAL TABLE t8 USING rtree(idx, x1, x2, y1, y2);
408    INSERT INTO t8 VALUES(1, 1.0, 1.0, 2.0, 2.0);
409    SELECT last_insert_rowid();
410  }
411} {1}
412do_test rtree-11.2 {
413  execsql {
414    INSERT INTO t8 VALUES(NULL, 1.0, 1.0, 2.0, 2.0);
415    SELECT last_insert_rowid();
416  }
417} {2}
418
419finish_test
420