xref: /sqlite-3.40.0/ext/rtree/rtreedoc.test (revision a2fef2f0)
1# 2021 September 13
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
20set testprefix rtreedoc
21
22# This command returns the number of columns in table $tbl within the
23# database opened by database handle $db
24proc column_count {db tbl} {
25  set nCol 0
26  $db eval "PRAGMA table_info = $tbl" { incr nCol }
27  return $nCol
28}
29
30proc column_name_list {db tbl} {
31  set lCol [list]
32  $db eval "PRAGMA table_info = $tbl" {
33    lappend lCol $name
34  }
35  return $lCol
36}
37
38#-------------------------------------------------------------------------
39#-------------------------------------------------------------------------
40# Section 3 of documentation.
41#-------------------------------------------------------------------------
42#-------------------------------------------------------------------------
43set testprefix rtreedoc-1
44
45# EVIDENCE-OF: R-15060-13876 A 1-dimensional R*Tree thus has 3 columns.
46do_execsql_test 1.1.1 { CREATE VIRTUAL TABLE rt1 USING rtree(id, x1,x2) }
47do_test         1.1.2 { column_count db rt1 } 3
48
49# EVIDENCE-OF: R-19353-19546 A 2-dimensional R*Tree has 5 columns.
50do_execsql_test 1.2.1 { CREATE VIRTUAL TABLE rt2 USING rtree(id,x1,x2, y1,y2) }
51do_test         1.2.2 { column_count db rt2 } 5
52
53# EVIDENCE-OF: R-13615-19528 A 3-dimensional R*Tree has 7 columns.
54do_execsql_test 1.3.1 {
55  CREATE VIRTUAL TABLE rt3 USING rtree(id, x1,x2, y1,y2, z1,z2)
56}
57do_test         1.3.2 { column_count db rt3 } 7
58
59# EVIDENCE-OF: R-53479-41922 A 4-dimensional R*Tree has 9 columns.
60do_execsql_test 1.4.1 {
61  CREATE VIRTUAL TABLE rt4 USING rtree(id, x1,x2, y1,y2, z1,z2, v1,v2)
62}
63do_test         1.4.2 { column_count db rt4 } 9
64
65# EVIDENCE-OF: R-13981-28768 And a 5-dimensional R*Tree has 11 columns.
66do_execsql_test 1.5.1 {
67  CREATE VIRTUAL TABLE rt5 USING rtree(id, x1,x2, y1,y2, z1,z2, v1,v2, w1,w2)
68}
69do_test         1.5.2 { column_count db rt5 } 11
70
71
72# Attempt to create r-tree tables with 6 and 7 dimensions.
73#
74# EVIDENCE-OF: R-61533-25862 The SQLite R*Tree implementation does not
75# support R*Trees wider than 5 dimensions.
76do_catchsql_test 2.1.1 {
77  CREATE VIRTUAL TABLE rt6 USING rtree(
78    id, x1,x2, y1,y2, z1,z2, v1,v2, w1,w2, a1,a2
79  )
80} {1 {Too many columns for an rtree table}}
81do_catchsql_test 2.1.2 {
82  CREATE VIRTUAL TABLE rt6 USING rtree(
83    id, x1,x2, y1,y2, z1,z2, v1,v2, w1,w2, a1,a2, b1, b2
84  )
85} {1 {Too many columns for an rtree table}}
86
87# Attempt to create r-tree tables with no columns, a single column, or
88# an even number of columns. This and the tests above establish that:
89#
90# EVIDENCE-OF: R-16717-50504 Each R*Tree index is a virtual table with
91# an odd number of columns between 3 and 11.
92foreach {tn cols err} {
93  1 ""                        "Too few columns for an rtree table"
94  2 "x"                       "Too few columns for an rtree table"
95  3 "x,y"                     "Too few columns for an rtree table"
96  4 "a,b,c,d"                 "Wrong number of columns for an rtree table"
97  5 "a,b,c,d,e,f"             "Wrong number of columns for an rtree table"
98  6 "a,b,c,d,e,f,g,h"         "Wrong number of columns for an rtree table"
99  7 "a,b,c,d,e,f,g,h,i,j"     "Wrong number of columns for an rtree table"
100  8 "a,b,c,d,e,f,g,h,i,j,k,l" "Too many columns for an rtree table"
101} {
102  do_catchsql_test 3.$tn "
103    CREATE VIRTUAL TABLE xyz USING rtree($cols)
104  " [list 1 $err]
105}
106
107# EVIDENCE-OF: R-46619-65417 The first column is always a 64-bit signed
108# integer primary key.
109#
110# EVIDENCE-OF: R-46866-24036 It may only store a 64-bit signed integer
111# value.
112#
113# EVIDENCE-OF: R-00250-64843 If an attempt is made to insert any other
114# non-integer value into this column, the r-tree module silently
115# converts it to an integer before writing it into the database.
116#
117do_execsql_test 4.0 { CREATE VIRTUAL TABLE rt USING rtree(id, x1, x2) }
118foreach {tn val res} {
119  1 10    10
120  2 10.6  10
121  3 10.99 10
122  4 '123' 123
123  5 X'313233'  123
124  6 -10   -10
125  7  9223372036854775807 9223372036854775807
126  8 -9223372036854775808 -9223372036854775808
127  9  '9223372036854775807' 9223372036854775807
128  10  '-9223372036854775808' -9223372036854775808
129  11  'hello+world' 0
130} {
131  do_execsql_test 4.$tn.1 "
132    DELETE FROM rt;
133    INSERT INTO rt VALUES($val, 10, 20);
134  "
135  do_execsql_test 4.$tn.2 {
136    SELECT typeof(id), id FROM rt
137  } [list integer $res]
138}
139
140# EVIDENCE-OF: R-15544-29079 Inserting a NULL value into this column
141# causes SQLite to automatically generate a new unique primary key
142# value.
143do_execsql_test 5.1 {
144  DELETE FROM rt;
145  INSERT INTO rt VALUES(100, 1, 2);
146  INSERT INTO rt VALUES(NULL, 1, 2);
147}
148do_execsql_test 5.2 { SELECT id FROM rt } {100 101}
149do_execsql_test 5.3 {
150  INSERT INTO rt VALUES(9223372036854775807, 1, 2);
151  INSERT INTO rt VALUES(NULL, 1, 2);
152}
153do_execsql_test 5.4 {
154  SELECT count(*) FROM rt;
155} 4
156do_execsql_test 5.5 {
157  SELECT id IN(100, 101, 9223372036854775807) FROM rt ORDER BY 1;
158} {0 1 1 1}
159
160
161# EVIDENCE-OF: R-64317-38978 The other columns are pairs, one pair per
162# dimension, containing the minimum and maximum values for that
163# dimension, respectively.
164#
165# Show this by observing that attempts to insert rows with max>min fail.
166#
167do_execsql_test 6.1 {
168  CREATE VIRTUAL TABLE rtF USING rtree(id, x1,x2, y1,y2);
169  CREATE VIRTUAL TABLE rtI USING rtree_i32(id, x1,x2, y1,y2, z1,z2);
170}
171foreach {tn x1 x2 y1 y2 ok} {
172  1   10.3 20.1   30.9 40.2   1
173  2   10.3 20.1   40.2 30.9   0
174  3   10.3 30.9   20.1 40.2   1
175  4   20.1 10.3   30.9 40.2   0
176} {
177  do_test 6.2.$tn {
178    catch { db eval { INSERT INTO rtF VALUES(NULL, $x1, $x2, $y1, $y2) } }
179  } [expr $ok==0]
180}
181foreach {tn x1 x2 y1 y2 z1 z2 ok} {
182  1   10 20   30 40  50 60  1
183  2   10 20   30 40  60 50  0
184  3   10 20   30 50  40 60  1
185  4   10 20   40 30  50 60  0
186  5   10 30   20 40  50 60  1
187  6   20 10   30 40  50 60  0
188} {
189  do_test 6.3.$tn {
190    catch { db eval { INSERT INTO rtI VALUES(NULL,$x1,$x2,$y1,$y2,$z1,$z2) } }
191  } [expr $ok==0]
192}
193
194# EVIDENCE-OF: R-08054-15429 The min/max-value pair columns are stored
195# as 32-bit floating point values for "rtree" virtual tables or as
196# 32-bit signed integers in "rtree_i32" virtual tables.
197#
198# Show this by showing that large values are rounded in ways consistent
199# with those two 32-bit types.
200do_execsql_test 7.1 {
201  DELETE FROM rtI;
202  INSERT INTO rtI VALUES(
203    0, -2000000000, 2000000000, -5000000000, 5000000000,
204    -1000000000000, 10000000000000
205  );
206  SELECT * FROM rtI;
207} {
208  0 -2000000000 2000000000 -705032704 705032704 727379968 1316134912
209}
210do_execsql_test 7.2 {
211  DELETE FROM rtF;
212  INSERT INTO rtF VALUES(
213    0, -2000000000, 2000000000,
214    -1000000000000, 10000000000000
215  );
216  SELECT * FROM rtF;
217} {
218  0 -2000000000.0 2000000000.0 -1000000126976.0 10000000876544.0
219}
220
221# EVIDENCE-OF: R-47371-54529 Unlike regular SQLite tables which can
222# store data in a variety of datatypes and formats, the R*Tree rigidly
223# enforce these storage types.
224#
225# EVIDENCE-OF: R-39153-14977 If any other type of value is inserted into
226# such a column, the r-tree module silently converts it to the required
227# type before writing the new record to the database.
228do_execsql_test 8.1 {
229  DELETE FROM rtI;
230  INSERT INTO rtI VALUES(
231    1, 'hello world', X'616263', NULL, 44.5, 1000, 9999.9999
232  );
233  SELECT * FROM rtI;
234} {
235  1   0 0    0 44    1000 9999
236}
237
238do_execsql_test 8.2 {
239  SELECT
240    typeof(x1), typeof(x2), typeof(y1), typeof(y2), typeof(z1), typeof(z2)
241  FROM rtI
242} {integer integer integer integer integer integer}
243
244do_execsql_test 8.3 {
245  DELETE FROM rtF;
246  INSERT INTO rtF VALUES(
247    1, 'hello world', X'616263', NULL, 44
248  );
249  SELECT * FROM rtF;
250} {
251  1   0.0 0.0    0.0 44.0
252}
253do_execsql_test 8.4 {
254  SELECT
255    typeof(x1), typeof(x2), typeof(y1), typeof(y2)
256  FROM rtF
257} {real real real real}
258
259
260
261
262#-------------------------------------------------------------------------
263#-------------------------------------------------------------------------
264# Section 3.1 of documentation.
265#-------------------------------------------------------------------------
266#-------------------------------------------------------------------------
267set testprefix rtreedoc-2
268reset_db
269
270foreach {tn name clist} {
271  1 t1 "id x1 x2"
272  2 t2 "id x1 x2   y1 y2   z1 z2"
273} {
274# EVIDENCE-OF: R-15142-18077 A new R*Tree index is created as follows:
275# CREATE VIRTUAL TABLE <name> USING rtree(<column-names>);
276  do_execsql_test 1.$tn.1 "
277    CREATE VIRTUAL TABLE $name USING rtree([join $clist ,])
278  "
279
280# EVIDENCE-OF: R-51698-09302 The <name> is the name your
281# application chooses for the R*Tree index and <column-names> is a
282# comma separated list of between 3 and 11 columns.
283  do_test 1.$tn.2 { column_name_list db $name } [list {*}$clist]
284
285# EVIDENCE-OF: R-50130-53472 The virtual <name> table creates
286# three shadow tables to actually store its content.
287  do_execsql_test 1.$tn.3 {
288    SELECT count(*) FROM sqlite_schema
289  } [expr 1+3]
290
291# EVIDENCE-OF: R-45256-35998 The names of these shadow tables are:
292# <name>_node <name>_rowid <name>_parent
293  do_execsql_test 1.$tn.4 {
294    SELECT name FROM sqlite_schema WHERE rootpage>0 ORDER BY 1
295  } [list ${name}_node ${name}_parent ${name}_rowid]
296
297  do_execsql_test 1.$tn.5 "DROP TABLE $name"
298}
299
300# EVIDENCE-OF: R-11241-54478 As an example, consider creating a
301# two-dimensional R*Tree index for use in spatial queries: CREATE
302# VIRTUAL TABLE demo_index USING rtree( id, -- Integer primary key minX,
303# maxX, -- Minimum and maximum X coordinate minY, maxY -- Minimum and
304# maximum Y coordinate );
305do_execsql_test 2.0 {
306  CREATE VIRTUAL TABLE demo_index USING rtree(
307      id,              -- Integer primary key
308      minX, maxX,      -- Minimum and maximum X coordinate
309      minY, maxY       -- Minimum and maximum Y coordinate
310  );
311  INSERT INTO demo_index VALUES(1,2,3,4,5);
312  INSERT INTO demo_index VALUES(6,7,8,9,10);
313}
314
315# EVIDENCE-OF: R-02287-33529 The shadow tables are ordinary SQLite data
316# tables.
317#
318# Ordinary tables. With ordinary sqlite_schema entries.
319do_execsql_test 2.1 {
320  SELECT * FROM sqlite_schema WHERE sql NOT LIKE '%virtual%'
321} {
322  table demo_index_rowid demo_index_rowid 2
323    {CREATE TABLE "demo_index_rowid"(rowid INTEGER PRIMARY KEY,nodeno)}
324  table demo_index_node demo_index_node 3
325    {CREATE TABLE "demo_index_node"(nodeno INTEGER PRIMARY KEY,data)}
326  table demo_index_parent demo_index_parent 4
327    {CREATE TABLE "demo_index_parent"(nodeno INTEGER PRIMARY KEY,parentnode)}
328}
329
330# EVIDENCE-OF: R-10863-13089 You can query them directly if you like,
331# though this unlikely to reveal anything particularly useful.
332#
333# Querying:
334do_execsql_test 2.2 {
335  SELECT count(*) FROM demo_index_node;
336  SELECT count(*) FROM demo_index_rowid;
337  SELECT count(*) FROM demo_index_parent;
338} {1 2 0}
339
340# EVIDENCE-OF: R-05650-46070 And you can UPDATE, DELETE, INSERT or even
341# DROP the shadow tables, though doing so will corrupt your R*Tree
342# index.
343do_execsql_test 2.3 {
344  DELETE FROM demo_index_rowid;
345  INSERT INTO demo_index_parent VALUES(2, 3);
346  UPDATE demo_index_node SET data = 'hello world'
347}
348do_catchsql_test 2.4 {
349  SELECT * FROM demo_index WHERE minX>10 AND maxX<30
350} {1 {database disk image is malformed}}
351do_execsql_test 2.5 {
352  DROP TABLE demo_index_rowid
353}
354
355#-------------------------------------------------------------------------
356#-------------------------------------------------------------------------
357# Section 3.1.1 of documentation.
358#-------------------------------------------------------------------------
359#-------------------------------------------------------------------------
360set testprefix rtreedoc-3
361reset_db
362
363# EVIDENCE-OF: R-44253-50720 In the argments to "rtree" in the CREATE
364# VIRTUAL TABLE statement, the names of the columns are taken from the
365# first token of each argument. All subsequent tokens within each
366# argument are silently ignored.
367#
368foreach {tn cols lCol} {
369  1 {(id TEXT, x1 TEXT, x2 TEXT, y1 TEXT, y2 TEXT)} {id x1 x2 y1 y2}
370  2 {(id TEXT, x1 UNIQUE, x2 TEXT, y1 NOT NULL, y2 TEXT)} {id x1 x2 y1 y2}
371  3 {(id, x1 DEFAULT 4, x2 TEXT, y1 NOT NULL, y2 TEXT)} {id x1 x2 y1 y2}
372} {
373  do_execsql_test 1.$tn.1 " CREATE VIRTUAL TABLE abc USING rtree $cols "
374  do_test 1.$tn.2 { column_name_list db abc } $lCol
375
376# EVIDENCE-OF: R-52032-06717 This means, for example, that if you try to
377# give a column a type affinity or add a constraint such as UNIQUE or
378# NOT NULL or DEFAULT to a column, those extra tokens are accepted as
379# valid, but they do not change the behavior of the rtree.
380
381  # Show there are no UNIQUE constraints
382  do_execsql_test 1.$tn.3 {
383    INSERT INTO abc VALUES(1, 10.0, 20.0, 10.0, 20.0);
384    INSERT INTO abc VALUES(2, 10.0, 20.0, 10.0, 20.0);
385  }
386
387  # Show the default values have not been modified
388  do_execsql_test 1.$tn.4 {
389    INSERT INTO abc DEFAULT VALUES;
390    SELECT * FROM abc WHERE rowid NOT IN (1,2)
391  } {3 0.0 0.0 0.0 0.0}
392
393  # Show that there are no NOT NULL constraints
394  do_execsql_test 1.$tn.5 {
395    INSERT INTO abc VALUES(NULL, NULL, NULL, NULL, NULL);
396    SELECT * FROM abc WHERE rowid NOT IN (1,2,3)
397  } {4 0.0 0.0 0.0 0.0}
398
399# EVIDENCE-OF: R-06893-30579 In an RTREE virtual table, the first column
400# always has a type affinity of INTEGER and all other data columns have
401# a type affinity of REAL.
402  do_execsql_test 1.$tn.5 {
403    INSERT INTO abc VALUES('5', '5', '5', '5', '5');
404    SELECT * FROM abc WHERE rowid NOT IN (1,2,3,4)
405  } {5 5.0 5.0 5.0 5.0}
406  do_execsql_test 1.$tn.6 {
407    SELECT type FROM pragma_table_info('abc') ORDER BY cid
408  } {INT REAL REAL REAL REAL}
409
410  do_execsql_test 1.$tn.7 " CREATE VIRTUAL TABLE abc2 USING rtree_i32 $cols "
411
412# EVIDENCE-OF: R-06224-52418 In an RTREE_I32 virtual table, all columns
413# have type affinity of INTEGER.
414  do_execsql_test 1.$tn.8 {
415    INSERT INTO abc2 VALUES('6.0', '6.0', '6.0', '6.0', '6.0');
416    SELECT * FROM abc2
417  } {6 6 6 6 6}
418  do_execsql_test 1.$tn.9 {
419    SELECT type FROM pragma_table_info('abc2') ORDER BY cid
420  } {INT INT INT INT INT}
421
422
423  do_execsql_test 1.$tn.10 {
424    DROP TABLE abc;
425    DROP TABLE abc2;
426  }
427}
428
429#-------------------------------------------------------------------------
430#-------------------------------------------------------------------------
431# Section 3.2 of documentation.
432#-------------------------------------------------------------------------
433#-------------------------------------------------------------------------
434set testprefix rtreedoc-4
435reset_db
436
437# EVIDENCE-OF: R-36195-31555 The usual INSERT, UPDATE, and DELETE
438# commands work on an R*Tree index just like on regular tables.
439#
440# Create a regular table and an rtree table. Perform INSERT, UPDATE and
441# DELETE operations, then observe that the contents of the two tables
442# are identical.
443do_execsql_test 1.0 {
444  CREATE VIRTUAL TABLE rt USING rtree(id, x1, x2);
445  CREATE TABLE t1(id INTEGER PRIMARY KEY, x1 REAL, x2 REAL);
446}
447foreach {tn sql} {
448  1 "INSERT INTO %TBL% VALUES(5, 11,12)"
449  2 "INSERT INTO %TBL% VALUES(11, -11,14.5)"
450  3 "UPDATE %TBL% SET x1=-99 WHERE id=11"
451  4 "DELETE FROM %TBL% WHERE x2=14.5"
452  5 "DELETE FROM %TBL%"
453} {
454  set sql1 [string map {%TBL% rt} $sql]
455  set sql2 [string map {%TBL% t1} $sql]
456  do_execsql_test 1.$tn.0 $sql1
457  do_execsql_test 1.$tn.1 $sql2
458
459  set data1 [execsql {SELECT * FROM rt ORDER BY 1}]
460  set data2 [execsql {SELECT * FROM t1 ORDER BY 1}]
461
462  set res [expr {$data1==$data2}]
463  do_test 1.$tn.2 {set res} 1
464}
465
466# EVIDENCE-OF: R-56987-45305
467do_execsql_test 2.0 {
468  CREATE VIRTUAL TABLE demo_index USING rtree(
469      id,              -- Integer primary key
470      minX, maxX,      -- Minimum and maximum X coordinate
471      minY, maxY       -- Minimum and maximum Y coordinate
472  );
473
474  INSERT INTO demo_index VALUES
475    (28215, -80.781227, -80.604706, 35.208813, 35.297367),
476    (28216, -80.957283, -80.840599, 35.235920, 35.367825),
477    (28217, -80.960869, -80.869431, 35.133682, 35.208233),
478    (28226, -80.878983, -80.778275, 35.060287, 35.154446),
479    (28227, -80.745544, -80.555382, 35.130215, 35.236916),
480    (28244, -80.844208, -80.841988, 35.223728, 35.225471),
481    (28262, -80.809074, -80.682938, 35.276207, 35.377747),
482    (28269, -80.851471, -80.735718, 35.272560, 35.407925),
483    (28270, -80.794983, -80.728966, 35.059872, 35.161823),
484    (28273, -80.994766, -80.875259, 35.074734, 35.172836),
485    (28277, -80.876793, -80.767586, 35.001709, 35.101063),
486    (28278, -81.058029, -80.956375, 35.044701, 35.223812),
487    (28280, -80.844208, -80.841972, 35.225468, 35.227203),
488    (28282, -80.846382, -80.844193, 35.223972, 35.225655);
489}
490
491#-------------------------------------------------------------------------
492#-------------------------------------------------------------------------
493# Section 3.3 of documentation.
494#-------------------------------------------------------------------------
495#-------------------------------------------------------------------------
496set testprefix rtreedoc-5
497reset_db
498
499
500
501
502#-------------------------------------------------------------------------
503#-------------------------------------------------------------------------
504# Section 3.4 of documentation.
505#-------------------------------------------------------------------------
506#-------------------------------------------------------------------------
507set testprefix rtreedoc-6
508
509# EVIDENCE-OF: R-08327-00674 By default, coordinates are stored in an
510# R*Tree using 32-bit floating point values.
511#
512# Show this by showing that rounding is consistent with 32-bit float
513# rounding.
514do_execsql_test 1.0 {
515  CREATE VIRTUAL TABLE rt USING rtree(id, a,b);
516}
517do_execsql_test 1.1 {
518  INSERT INTO rt VALUES(14, -1000000000000, 1000000000000);
519  SELECT * FROM rt;
520} {14 -1000000126976.0 1000000126976.0}
521
522# EVIDENCE-OF: R-39127-51288 When a coordinate cannot be exactly
523# represented by a 32-bit floating point number, the lower-bound
524# coordinates are rounded down and the upper-bound coordinates are
525# rounded up.
526foreach {tn val} {
527  1 100000000000
528  2 200000000000
529  3 300000000000
530  4 400000000000
531
532  5 -100000000000
533  6 -200000000000
534  7 -300000000000
535  8 -400000000000
536} {
537  set val [expr $val]
538  do_execsql_test 2.$tn.0 {DELETE FROM rt}
539  do_execsql_test 2.$tn.1 {INSERT INTO rt VALUES(23, $val, $val)}
540  do_execsql_test 2.$tn.2 {
541    SELECT $val>=a, $val<=b, a!=b FROM rt
542  } {1 1 1}
543}
544
545do_execsql_test 3.0 {
546  DROP TABLE rt;
547  CREATE VIRTUAL TABLE rt USING rtree(id, x1,x2, y1,y2);
548}
549
550# EVIDENCE-OF: R-45870-62834 Thus, bounding boxes might be slightly
551# larger than specified, but will never be any smaller.
552foreach {tn x1 x2 y1 y2} {
553  1 100000000000 200000000000 300000000000 400000000000
554} {
555  set val [expr $val]
556  do_execsql_test 3.$tn.0 {DELETE FROM rt}
557  do_execsql_test 3.$tn.1 {INSERT INTO rt VALUES(23, $x1, $x2, $y1, $y2)}
558  do_execsql_test 3.$tn.2 {
559    SELECT (x2-x1)*(y2-y1) >= ($x2-$x1)*($y2-$y1) FROM rt
560  } {1}
561}
562
563#-------------------------------------------------------------------------
564#-------------------------------------------------------------------------
565# Section 3.5 of documentation.
566#-------------------------------------------------------------------------
567#-------------------------------------------------------------------------
568set testprefix rtreedoc-7
569reset_db
570
571# EVIDENCE-OF: R-55979-39402 It is the nature of the Guttman R-Tree
572# algorithm that any write might radically restructure the tree, and in
573# the process change the scan order of the nodes.
574#
575# In the test below, the INSERT marked "THIS INSERT!!" does not affect
576# the results of queries with an ORDER BY, but does affect the results
577# of one without an ORDER BY. Therefore the INSERT changed the scan
578# order.
579do_execsql_test 1.0 {
580  CREATE VIRTUAL TABLE rt USING rtree(id, minX, maxX);
581  WITH s(i) AS (
582    SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<51
583  )
584  INSERT INTO rt SELECT NULL, i%10, (i%10)+5 FROM s
585}
586do_execsql_test 1.1 { SELECT count(*) FROM rt_node } 1
587do_test 1.2 {
588  set res1 [db eval {SELECT * FROM rt WHERE maxX < 30}]
589  set res1o [db eval {SELECT * FROM rt WHERE maxX < 30 ORDER BY +id}]
590
591  db eval { INSERT INTO rt VALUES(NULL, 50, 50) }   ;# THIS INSERT!!
592
593  set res2 [db eval {SELECT * FROM rt WHERE maxX < 30}]
594  set res2o [db eval {SELECT * FROM rt WHERE maxX < 30 ORDER BY +id}]
595  list [expr {$res1==$res2}] [expr {$res1o==$res2o}]
596} {0 1}
597
598do_execsql_test 1.3 { SELECT count(*) FROM rt_node } 3
599
600# EVIDENCE-OF: R-00683-48865 For this reason, it is not generally
601# possible to modify the R-Tree in the middle of a query of the R-Tree.
602# Attempts to do so will fail with a SQLITE_LOCKED "database table is
603# locked" error.
604#
605# SQLITE_LOCKED==6
606#
607do_test 1.4 {
608  set nCnt 3
609  db eval { SELECT * FROM rt WHERE minX>0 AND maxX<12 } {
610    incr nCnt -1
611    if {$nCnt==0} {
612      set rc [catch {db eval {
613        INSERT INTO rt VALUES(NULL, 51, 51);
614      }} msg]
615      set errorcode [db errorcode]
616      break
617    }
618  }
619
620  list $errorcode $rc $msg
621} {6 1 {database table is locked}}
622
623# EVIDENCE-OF: R-19740-29710 So, for example, suppose an application
624# runs one query against an R-Tree like this: SELECT id FROM demo_index
625# WHERE maxY>=35.0 AND minY<=35.0; Then for each "id" value
626# returned, suppose the application creates an UPDATE statement like the
627# following and binds the "id" value returned against the "?1"
628# parameter: UPDATE demo_index SET maxY=maxY+0.5 WHERE id=?1;
629#
630# EVIDENCE-OF: R-52919-32711 Then the UPDATE might fail with an
631# SQLITE_LOCKED error.
632do_execsql_test 2.0 {
633  CREATE VIRTUAL TABLE demo_index USING rtree(
634      id,              -- Integer primary key
635      minX, maxX,      -- Minimum and maximum X coordinate
636      minY, maxY       -- Minimum and maximum Y coordinate
637  );
638  INSERT INTO demo_index VALUES
639    (28215, -80.781227, -80.604706, 35.208813, 35.297367),
640    (28216, -80.957283, -80.840599, 35.235920, 35.367825),
641    (28217, -80.960869, -80.869431, 35.133682, 35.208233),
642    (28226, -80.878983, -80.778275, 35.060287, 35.154446);
643}
644do_test 2.1 {
645  db eval { SELECT id FROM demo_index WHERE maxY>=35.0  AND minY<=35.0 } {
646    set rc [catch {
647      db eval { UPDATE demo_index SET maxY=maxY+0.5 WHERE id=$id }
648    } msg]
649    set errorcode [db errorcode]
650    break
651  }
652  list $errorcode $rc $msg
653} {6 1 {database table is locked}}
654
655# EVIDENCE-OF: R-32604-49843 Ordinary tables in SQLite are able to read
656# and write at the same time.
657#
658do_execsql_test 3.0 {
659  CREATE TABLE x1(a INTEGER PRIMARY KEY, b, c);
660  INSERT INTO x1 VALUES(1, 1, 1);
661  INSERT INTO x1 VALUES(2, 2, 2);
662  INSERT INTO x1 VALUES(3, 3, 3);
663  INSERT INTO x1 VALUES(4, 4, 4);
664}
665do_test 3.1 {
666  set res [list]
667  db eval { SELECT * FROM x1 } {
668    lappend res $a $b $c
669    switch -- $a {
670      1 {
671        db eval { INSERT INTO x1 VALUES(5, 5, 5) }
672      }
673      2 {
674        db eval { UPDATE x1 SET c=20 WHERE a=2 }
675      }
676      3 {
677        db eval { DELETE FROM x1 WHERE c IN (3,4) }
678      }
679    }
680  }
681  set res
682} {1 1 1 2 2 2 3 3 3 5 5 5}
683do_execsql_test 3.2 {
684  SELECT * FROM x1
685} {1 1 1  2 2 20  5 5 5}
686
687# EVIDENCE-OF: R-06177-00576 And R-Tree can appear to read and write at
688# the same time in some circumstances, if it can figure out how to
689# reliably run the query to completion before starting the update.
690#
691# In 8.2, it can, it 8.1, it cannot.
692do_test 8.1 {
693  db eval { SELECT * FROM rt } {
694    set rc [catch { db eval { INSERT INTO rt VALUES(53,53,53) } } msg]
695    break;
696  }
697  list $rc $msg
698} {1 {database table is locked}}
699do_test 8.2 {
700  db eval { SELECT * FROM rt ORDER BY +id } {
701    set rc [catch { db eval { INSERT INTO rt VALUES(53,53,53) } } msg]
702    break
703  }
704  list $rc $msg
705} {0 {}}
706
707#-------------------------------------------------------------------------
708#-------------------------------------------------------------------------
709# Section 4 of documentation.
710#-------------------------------------------------------------------------
711#-------------------------------------------------------------------------
712set testprefix rtreedoc-8
713
714
715finish_test
716
717