xref: /sqlite-3.40.0/ext/rtree/rtreedoc.test (revision dcf10a1a)
130918bfbSdan# 2021 September 13
230918bfbSdan#
330918bfbSdan# The author disclaims copyright to this source code.  In place of
430918bfbSdan# a legal notice, here is a blessing:
530918bfbSdan#
630918bfbSdan#    May you do good and not evil.
730918bfbSdan#    May you find forgiveness for yourself and forgive others.
830918bfbSdan#    May you share freely, never taking more than you give.
930918bfbSdan#
1030918bfbSdan#***********************************************************************
1130918bfbSdan#
1230918bfbSdan# The focus of this file is testing the r-tree extension.
1330918bfbSdan#
1430918bfbSdan
1530918bfbSdanif {![info exists testdir]} {
1630918bfbSdan  set testdir [file join [file dirname [info script]] .. .. test]
1730918bfbSdan}
1830918bfbSdansource [file join [file dirname [info script]] rtree_util.tcl]
1930918bfbSdansource $testdir/tester.tcl
2030918bfbSdanset testprefix rtreedoc
2130918bfbSdan
225f835b78Sdanifcapable !rtree {
235f835b78Sdan  finish_test
245f835b78Sdan  return
255f835b78Sdan}
265f835b78Sdan
2730918bfbSdan# This command returns the number of columns in table $tbl within the
2830918bfbSdan# database opened by database handle $db
2930918bfbSdanproc column_count {db tbl} {
3030918bfbSdan  set nCol 0
3130918bfbSdan  $db eval "PRAGMA table_info = $tbl" { incr nCol }
3230918bfbSdan  return $nCol
3330918bfbSdan}
3430918bfbSdan
35db45212aSdanproc column_name_list {db tbl} {
36db45212aSdan  set lCol [list]
37db45212aSdan  $db eval "PRAGMA table_info = $tbl" {
38db45212aSdan    lappend lCol $name
39db45212aSdan  }
40db45212aSdan  return $lCol
41db45212aSdan}
42*dcf10a1aSdrhunset -nocomplain res
43db45212aSdan
4430918bfbSdan#-------------------------------------------------------------------------
4530918bfbSdan#-------------------------------------------------------------------------
4630918bfbSdan# Section 3 of documentation.
4730918bfbSdan#-------------------------------------------------------------------------
4830918bfbSdan#-------------------------------------------------------------------------
49db45212aSdanset testprefix rtreedoc-1
5030918bfbSdan
5130918bfbSdan# EVIDENCE-OF: R-15060-13876 A 1-dimensional R*Tree thus has 3 columns.
5230918bfbSdando_execsql_test 1.1.1 { CREATE VIRTUAL TABLE rt1 USING rtree(id, x1,x2) }
5330918bfbSdando_test         1.1.2 { column_count db rt1 } 3
5430918bfbSdan
5530918bfbSdan# EVIDENCE-OF: R-19353-19546 A 2-dimensional R*Tree has 5 columns.
5630918bfbSdando_execsql_test 1.2.1 { CREATE VIRTUAL TABLE rt2 USING rtree(id,x1,x2, y1,y2) }
5730918bfbSdando_test         1.2.2 { column_count db rt2 } 5
5830918bfbSdan
5930918bfbSdan# EVIDENCE-OF: R-13615-19528 A 3-dimensional R*Tree has 7 columns.
6030918bfbSdando_execsql_test 1.3.1 {
6130918bfbSdan  CREATE VIRTUAL TABLE rt3 USING rtree(id, x1,x2, y1,y2, z1,z2)
6230918bfbSdan}
6330918bfbSdando_test         1.3.2 { column_count db rt3 } 7
6430918bfbSdan
6530918bfbSdan# EVIDENCE-OF: R-53479-41922 A 4-dimensional R*Tree has 9 columns.
6630918bfbSdando_execsql_test 1.4.1 {
6730918bfbSdan  CREATE VIRTUAL TABLE rt4 USING rtree(id, x1,x2, y1,y2, z1,z2, v1,v2)
6830918bfbSdan}
6930918bfbSdando_test         1.4.2 { column_count db rt4 } 9
7030918bfbSdan
7130918bfbSdan# EVIDENCE-OF: R-13981-28768 And a 5-dimensional R*Tree has 11 columns.
7230918bfbSdando_execsql_test 1.5.1 {
7330918bfbSdan  CREATE VIRTUAL TABLE rt5 USING rtree(id, x1,x2, y1,y2, z1,z2, v1,v2, w1,w2)
7430918bfbSdan}
7530918bfbSdando_test         1.5.2 { column_count db rt5 } 11
7630918bfbSdan
7730918bfbSdan
7830918bfbSdan# Attempt to create r-tree tables with 6 and 7 dimensions.
7930918bfbSdan#
8030918bfbSdan# EVIDENCE-OF: R-61533-25862 The SQLite R*Tree implementation does not
8130918bfbSdan# support R*Trees wider than 5 dimensions.
8230918bfbSdando_catchsql_test 2.1.1 {
8330918bfbSdan  CREATE VIRTUAL TABLE rt6 USING rtree(
8430918bfbSdan    id, x1,x2, y1,y2, z1,z2, v1,v2, w1,w2, a1,a2
8530918bfbSdan  )
8630918bfbSdan} {1 {Too many columns for an rtree table}}
8730918bfbSdando_catchsql_test 2.1.2 {
8830918bfbSdan  CREATE VIRTUAL TABLE rt6 USING rtree(
8930918bfbSdan    id, x1,x2, y1,y2, z1,z2, v1,v2, w1,w2, a1,a2, b1, b2
9030918bfbSdan  )
9130918bfbSdan} {1 {Too many columns for an rtree table}}
9230918bfbSdan
9330918bfbSdan# Attempt to create r-tree tables with no columns, a single column, or
9430918bfbSdan# an even number of columns. This and the tests above establish that:
9530918bfbSdan#
9630918bfbSdan# EVIDENCE-OF: R-16717-50504 Each R*Tree index is a virtual table with
9730918bfbSdan# an odd number of columns between 3 and 11.
9830918bfbSdanforeach {tn cols err} {
9930918bfbSdan  1 ""                        "Too few columns for an rtree table"
10030918bfbSdan  2 "x"                       "Too few columns for an rtree table"
10130918bfbSdan  3 "x,y"                     "Too few columns for an rtree table"
10230918bfbSdan  4 "a,b,c,d"                 "Wrong number of columns for an rtree table"
10330918bfbSdan  5 "a,b,c,d,e,f"             "Wrong number of columns for an rtree table"
10430918bfbSdan  6 "a,b,c,d,e,f,g,h"         "Wrong number of columns for an rtree table"
10530918bfbSdan  7 "a,b,c,d,e,f,g,h,i,j"     "Wrong number of columns for an rtree table"
10630918bfbSdan  8 "a,b,c,d,e,f,g,h,i,j,k,l" "Too many columns for an rtree table"
10730918bfbSdan} {
10830918bfbSdan  do_catchsql_test 3.$tn "
10930918bfbSdan    CREATE VIRTUAL TABLE xyz USING rtree($cols)
11030918bfbSdan  " [list 1 $err]
11130918bfbSdan}
11230918bfbSdan
11372fb42d5Sdan# EVIDENCE-OF: R-17874-21123 The first column of an SQLite R*Tree is
11472fb42d5Sdan# similar to an integer primary key column of a normal SQLite table.
11572fb42d5Sdan#
11630918bfbSdan# EVIDENCE-OF: R-46619-65417 The first column is always a 64-bit signed
11730918bfbSdan# integer primary key.
11830918bfbSdan#
11930918bfbSdan# EVIDENCE-OF: R-46866-24036 It may only store a 64-bit signed integer
12030918bfbSdan# value.
12130918bfbSdan#
12230918bfbSdan# EVIDENCE-OF: R-00250-64843 If an attempt is made to insert any other
12330918bfbSdan# non-integer value into this column, the r-tree module silently
12430918bfbSdan# converts it to an integer before writing it into the database.
12530918bfbSdan#
12630918bfbSdando_execsql_test 4.0 { CREATE VIRTUAL TABLE rt USING rtree(id, x1, x2) }
12730918bfbSdanforeach {tn val res} {
12830918bfbSdan  1 10    10
12930918bfbSdan  2 10.6  10
13030918bfbSdan  3 10.99 10
13130918bfbSdan  4 '123' 123
13230918bfbSdan  5 X'313233'  123
13330918bfbSdan  6 -10   -10
13430918bfbSdan  7  9223372036854775807 9223372036854775807
13530918bfbSdan  8 -9223372036854775808 -9223372036854775808
13630918bfbSdan  9  '9223372036854775807' 9223372036854775807
13730918bfbSdan  10  '-9223372036854775808' -9223372036854775808
13830918bfbSdan  11  'hello+world' 0
13930918bfbSdan} {
14030918bfbSdan  do_execsql_test 4.$tn.1 "
14130918bfbSdan    DELETE FROM rt;
14230918bfbSdan    INSERT INTO rt VALUES($val, 10, 20);
14330918bfbSdan  "
14430918bfbSdan  do_execsql_test 4.$tn.2 {
14530918bfbSdan    SELECT typeof(id), id FROM rt
14630918bfbSdan  } [list integer $res]
14730918bfbSdan}
14830918bfbSdan
14930918bfbSdan# EVIDENCE-OF: R-15544-29079 Inserting a NULL value into this column
15030918bfbSdan# causes SQLite to automatically generate a new unique primary key
15130918bfbSdan# value.
15230918bfbSdando_execsql_test 5.1 {
15330918bfbSdan  DELETE FROM rt;
15430918bfbSdan  INSERT INTO rt VALUES(100, 1, 2);
15530918bfbSdan  INSERT INTO rt VALUES(NULL, 1, 2);
15630918bfbSdan}
15730918bfbSdando_execsql_test 5.2 { SELECT id FROM rt } {100 101}
15830918bfbSdando_execsql_test 5.3 {
15930918bfbSdan  INSERT INTO rt VALUES(9223372036854775807, 1, 2);
16030918bfbSdan  INSERT INTO rt VALUES(NULL, 1, 2);
16130918bfbSdan}
16230918bfbSdando_execsql_test 5.4 {
16330918bfbSdan  SELECT count(*) FROM rt;
16430918bfbSdan} 4
16530918bfbSdando_execsql_test 5.5 {
16630918bfbSdan  SELECT id IN(100, 101, 9223372036854775807) FROM rt ORDER BY 1;
16730918bfbSdan} {0 1 1 1}
16830918bfbSdan
16930918bfbSdan
17030918bfbSdan# EVIDENCE-OF: R-64317-38978 The other columns are pairs, one pair per
17130918bfbSdan# dimension, containing the minimum and maximum values for that
17230918bfbSdan# dimension, respectively.
17330918bfbSdan#
17430918bfbSdan# Show this by observing that attempts to insert rows with max>min fail.
17530918bfbSdan#
17630918bfbSdando_execsql_test 6.1 {
17730918bfbSdan  CREATE VIRTUAL TABLE rtF USING rtree(id, x1,x2, y1,y2);
17830918bfbSdan  CREATE VIRTUAL TABLE rtI USING rtree_i32(id, x1,x2, y1,y2, z1,z2);
17930918bfbSdan}
18030918bfbSdanforeach {tn x1 x2 y1 y2 ok} {
18130918bfbSdan  1   10.3 20.1   30.9 40.2   1
18230918bfbSdan  2   10.3 20.1   40.2 30.9   0
18330918bfbSdan  3   10.3 30.9   20.1 40.2   1
18430918bfbSdan  4   20.1 10.3   30.9 40.2   0
18530918bfbSdan} {
18630918bfbSdan  do_test 6.2.$tn {
18730918bfbSdan    catch { db eval { INSERT INTO rtF VALUES(NULL, $x1, $x2, $y1, $y2) } }
18830918bfbSdan  } [expr $ok==0]
18930918bfbSdan}
19030918bfbSdanforeach {tn x1 x2 y1 y2 z1 z2 ok} {
19130918bfbSdan  1   10 20   30 40  50 60  1
19230918bfbSdan  2   10 20   30 40  60 50  0
19330918bfbSdan  3   10 20   30 50  40 60  1
19430918bfbSdan  4   10 20   40 30  50 60  0
19530918bfbSdan  5   10 30   20 40  50 60  1
19630918bfbSdan  6   20 10   30 40  50 60  0
19730918bfbSdan} {
19830918bfbSdan  do_test 6.3.$tn {
19930918bfbSdan    catch { db eval { INSERT INTO rtI VALUES(NULL,$x1,$x2,$y1,$y2,$z1,$z2) } }
20030918bfbSdan  } [expr $ok==0]
20130918bfbSdan}
20230918bfbSdan
20330918bfbSdan# EVIDENCE-OF: R-08054-15429 The min/max-value pair columns are stored
20430918bfbSdan# as 32-bit floating point values for "rtree" virtual tables or as
20530918bfbSdan# 32-bit signed integers in "rtree_i32" virtual tables.
20630918bfbSdan#
20730918bfbSdan# Show this by showing that large values are rounded in ways consistent
20830918bfbSdan# with those two 32-bit types.
20930918bfbSdando_execsql_test 7.1 {
21030918bfbSdan  DELETE FROM rtI;
21130918bfbSdan  INSERT INTO rtI VALUES(
21230918bfbSdan    0, -2000000000, 2000000000, -5000000000, 5000000000,
21330918bfbSdan    -1000000000000, 10000000000000
21430918bfbSdan  );
21530918bfbSdan  SELECT * FROM rtI;
21630918bfbSdan} {
21730918bfbSdan  0 -2000000000 2000000000 -705032704 705032704 727379968 1316134912
21830918bfbSdan}
21930918bfbSdando_execsql_test 7.2 {
22030918bfbSdan  DELETE FROM rtF;
22130918bfbSdan  INSERT INTO rtF VALUES(
22230918bfbSdan    0, -2000000000, 2000000000,
22330918bfbSdan    -1000000000000, 10000000000000
22430918bfbSdan  );
22530918bfbSdan  SELECT * FROM rtF;
22630918bfbSdan} {
22730918bfbSdan  0 -2000000000.0 2000000000.0 -1000000126976.0 10000000876544.0
22830918bfbSdan}
22930918bfbSdan
23030918bfbSdan# EVIDENCE-OF: R-47371-54529 Unlike regular SQLite tables which can
23130918bfbSdan# store data in a variety of datatypes and formats, the R*Tree rigidly
23230918bfbSdan# enforce these storage types.
23330918bfbSdan#
23430918bfbSdan# EVIDENCE-OF: R-39153-14977 If any other type of value is inserted into
23530918bfbSdan# such a column, the r-tree module silently converts it to the required
23630918bfbSdan# type before writing the new record to the database.
23730918bfbSdando_execsql_test 8.1 {
23830918bfbSdan  DELETE FROM rtI;
23930918bfbSdan  INSERT INTO rtI VALUES(
24030918bfbSdan    1, 'hello world', X'616263', NULL, 44.5, 1000, 9999.9999
24130918bfbSdan  );
24230918bfbSdan  SELECT * FROM rtI;
24330918bfbSdan} {
24430918bfbSdan  1   0 0    0 44    1000 9999
24530918bfbSdan}
24630918bfbSdan
24730918bfbSdando_execsql_test 8.2 {
24830918bfbSdan  SELECT
24930918bfbSdan    typeof(x1), typeof(x2), typeof(y1), typeof(y2), typeof(z1), typeof(z2)
25030918bfbSdan  FROM rtI
25130918bfbSdan} {integer integer integer integer integer integer}
25230918bfbSdan
25330918bfbSdando_execsql_test 8.3 {
25430918bfbSdan  DELETE FROM rtF;
25530918bfbSdan  INSERT INTO rtF VALUES(
25630918bfbSdan    1, 'hello world', X'616263', NULL, 44
25730918bfbSdan  );
25830918bfbSdan  SELECT * FROM rtF;
25930918bfbSdan} {
26030918bfbSdan  1   0.0 0.0    0.0 44.0
26130918bfbSdan}
26230918bfbSdando_execsql_test 8.4 {
26330918bfbSdan  SELECT
26430918bfbSdan    typeof(x1), typeof(x2), typeof(y1), typeof(y2)
26530918bfbSdan  FROM rtF
26630918bfbSdan} {real real real real}
26730918bfbSdan
26830918bfbSdan
26930918bfbSdan
27030918bfbSdan
27130918bfbSdan#-------------------------------------------------------------------------
272db45212aSdan#-------------------------------------------------------------------------
273db45212aSdan# Section 3.1 of documentation.
274db45212aSdan#-------------------------------------------------------------------------
275db45212aSdan#-------------------------------------------------------------------------
276db45212aSdanset testprefix rtreedoc-2
277db45212aSdanreset_db
278db45212aSdan
279db45212aSdanforeach {tn name clist} {
280db45212aSdan  1 t1 "id x1 x2"
281db45212aSdan  2 t2 "id x1 x2   y1 y2   z1 z2"
282db45212aSdan} {
283db45212aSdan# EVIDENCE-OF: R-15142-18077 A new R*Tree index is created as follows:
284db45212aSdan# CREATE VIRTUAL TABLE <name> USING rtree(<column-names>);
285db45212aSdan  do_execsql_test 1.$tn.1 "
286db45212aSdan    CREATE VIRTUAL TABLE $name USING rtree([join $clist ,])
287db45212aSdan  "
288db45212aSdan
289db45212aSdan# EVIDENCE-OF: R-51698-09302 The <name> is the name your
290db45212aSdan# application chooses for the R*Tree index and <column-names> is a
291db45212aSdan# comma separated list of between 3 and 11 columns.
292db45212aSdan  do_test 1.$tn.2 { column_name_list db $name } [list {*}$clist]
293db45212aSdan
294db45212aSdan# EVIDENCE-OF: R-50130-53472 The virtual <name> table creates
295db45212aSdan# three shadow tables to actually store its content.
296db45212aSdan  do_execsql_test 1.$tn.3 {
297db45212aSdan    SELECT count(*) FROM sqlite_schema
298db45212aSdan  } [expr 1+3]
299db45212aSdan
300db45212aSdan# EVIDENCE-OF: R-45256-35998 The names of these shadow tables are:
301db45212aSdan# <name>_node <name>_rowid <name>_parent
302db45212aSdan  do_execsql_test 1.$tn.4 {
303db45212aSdan    SELECT name FROM sqlite_schema WHERE rootpage>0 ORDER BY 1
304db45212aSdan  } [list ${name}_node ${name}_parent ${name}_rowid]
305db45212aSdan
306db45212aSdan  do_execsql_test 1.$tn.5 "DROP TABLE $name"
307db45212aSdan}
308db45212aSdan
309db45212aSdan# EVIDENCE-OF: R-11241-54478 As an example, consider creating a
310db45212aSdan# two-dimensional R*Tree index for use in spatial queries: CREATE
311db45212aSdan# VIRTUAL TABLE demo_index USING rtree( id, -- Integer primary key minX,
312db45212aSdan# maxX, -- Minimum and maximum X coordinate minY, maxY -- Minimum and
313db45212aSdan# maximum Y coordinate );
314db45212aSdando_execsql_test 2.0 {
315db45212aSdan  CREATE VIRTUAL TABLE demo_index USING rtree(
316db45212aSdan      id,              -- Integer primary key
317db45212aSdan      minX, maxX,      -- Minimum and maximum X coordinate
318db45212aSdan      minY, maxY       -- Minimum and maximum Y coordinate
319db45212aSdan  );
320db45212aSdan  INSERT INTO demo_index VALUES(1,2,3,4,5);
321db45212aSdan  INSERT INTO demo_index VALUES(6,7,8,9,10);
322db45212aSdan}
323db45212aSdan
324db45212aSdan# EVIDENCE-OF: R-02287-33529 The shadow tables are ordinary SQLite data
325db45212aSdan# tables.
326db45212aSdan#
327db45212aSdan# Ordinary tables. With ordinary sqlite_schema entries.
328db45212aSdando_execsql_test 2.1 {
32909e2626eSdan  SELECT type, name, sql FROM sqlite_schema WHERE sql NOT LIKE '%virtual%'
330db45212aSdan} {
33109e2626eSdan  table demo_index_rowid
332db45212aSdan    {CREATE TABLE "demo_index_rowid"(rowid INTEGER PRIMARY KEY,nodeno)}
33309e2626eSdan  table demo_index_node
334db45212aSdan    {CREATE TABLE "demo_index_node"(nodeno INTEGER PRIMARY KEY,data)}
33509e2626eSdan  table demo_index_parent
336db45212aSdan    {CREATE TABLE "demo_index_parent"(nodeno INTEGER PRIMARY KEY,parentnode)}
337db45212aSdan}
338db45212aSdan
339db45212aSdan# EVIDENCE-OF: R-10863-13089 You can query them directly if you like,
340db45212aSdan# though this unlikely to reveal anything particularly useful.
341db45212aSdan#
342db45212aSdan# Querying:
343db45212aSdando_execsql_test 2.2 {
344db45212aSdan  SELECT count(*) FROM demo_index_node;
345db45212aSdan  SELECT count(*) FROM demo_index_rowid;
346db45212aSdan  SELECT count(*) FROM demo_index_parent;
347db45212aSdan} {1 2 0}
348db45212aSdan
349db45212aSdan# EVIDENCE-OF: R-05650-46070 And you can UPDATE, DELETE, INSERT or even
350db45212aSdan# DROP the shadow tables, though doing so will corrupt your R*Tree
351db45212aSdan# index.
352db45212aSdando_execsql_test 2.3 {
353db45212aSdan  DELETE FROM demo_index_rowid;
354db45212aSdan  INSERT INTO demo_index_parent VALUES(2, 3);
355db45212aSdan  UPDATE demo_index_node SET data = 'hello world'
356db45212aSdan}
357db45212aSdando_catchsql_test 2.4 {
358db45212aSdan  SELECT * FROM demo_index WHERE minX>10 AND maxX<30
359db45212aSdan} {1 {database disk image is malformed}}
360db45212aSdando_execsql_test 2.5 {
361db45212aSdan  DROP TABLE demo_index_rowid
362db45212aSdan}
363db45212aSdan
364db45212aSdan#-------------------------------------------------------------------------
365db45212aSdan#-------------------------------------------------------------------------
366db45212aSdan# Section 3.1.1 of documentation.
367db45212aSdan#-------------------------------------------------------------------------
368db45212aSdan#-------------------------------------------------------------------------
369db45212aSdanset testprefix rtreedoc-3
370db45212aSdanreset_db
371db45212aSdan
372db45212aSdan# EVIDENCE-OF: R-44253-50720 In the argments to "rtree" in the CREATE
373db45212aSdan# VIRTUAL TABLE statement, the names of the columns are taken from the
374db45212aSdan# first token of each argument. All subsequent tokens within each
375db45212aSdan# argument are silently ignored.
376db45212aSdan#
377db45212aSdanforeach {tn cols lCol} {
378db45212aSdan  1 {(id TEXT, x1 TEXT, x2 TEXT, y1 TEXT, y2 TEXT)} {id x1 x2 y1 y2}
379db45212aSdan  2 {(id TEXT, x1 UNIQUE, x2 TEXT, y1 NOT NULL, y2 TEXT)} {id x1 x2 y1 y2}
380db45212aSdan  3 {(id, x1 DEFAULT 4, x2 TEXT, y1 NOT NULL, y2 TEXT)} {id x1 x2 y1 y2}
381db45212aSdan} {
382db45212aSdan  do_execsql_test 1.$tn.1 " CREATE VIRTUAL TABLE abc USING rtree $cols "
383db45212aSdan  do_test 1.$tn.2 { column_name_list db abc } $lCol
384db45212aSdan
385db45212aSdan# EVIDENCE-OF: R-52032-06717 This means, for example, that if you try to
386db45212aSdan# give a column a type affinity or add a constraint such as UNIQUE or
387db45212aSdan# NOT NULL or DEFAULT to a column, those extra tokens are accepted as
388db45212aSdan# valid, but they do not change the behavior of the rtree.
389db45212aSdan
390db45212aSdan  # Show there are no UNIQUE constraints
391db45212aSdan  do_execsql_test 1.$tn.3 {
392db45212aSdan    INSERT INTO abc VALUES(1, 10.0, 20.0, 10.0, 20.0);
393db45212aSdan    INSERT INTO abc VALUES(2, 10.0, 20.0, 10.0, 20.0);
394db45212aSdan  }
395db45212aSdan
396db45212aSdan  # Show the default values have not been modified
397db45212aSdan  do_execsql_test 1.$tn.4 {
398db45212aSdan    INSERT INTO abc DEFAULT VALUES;
399db45212aSdan    SELECT * FROM abc WHERE rowid NOT IN (1,2)
400db45212aSdan  } {3 0.0 0.0 0.0 0.0}
401db45212aSdan
402db45212aSdan  # Show that there are no NOT NULL constraints
403db45212aSdan  do_execsql_test 1.$tn.5 {
404db45212aSdan    INSERT INTO abc VALUES(NULL, NULL, NULL, NULL, NULL);
405db45212aSdan    SELECT * FROM abc WHERE rowid NOT IN (1,2,3)
406db45212aSdan  } {4 0.0 0.0 0.0 0.0}
407db45212aSdan
408db45212aSdan# EVIDENCE-OF: R-06893-30579 In an RTREE virtual table, the first column
409db45212aSdan# always has a type affinity of INTEGER and all other data columns have
410db45212aSdan# a type affinity of REAL.
411db45212aSdan  do_execsql_test 1.$tn.5 {
412db45212aSdan    INSERT INTO abc VALUES('5', '5', '5', '5', '5');
413db45212aSdan    SELECT * FROM abc WHERE rowid NOT IN (1,2,3,4)
414db45212aSdan  } {5 5.0 5.0 5.0 5.0}
415db45212aSdan  do_execsql_test 1.$tn.6 {
416db45212aSdan    SELECT type FROM pragma_table_info('abc') ORDER BY cid
417db45212aSdan  } {INT REAL REAL REAL REAL}
418db45212aSdan
419db45212aSdan  do_execsql_test 1.$tn.7 " CREATE VIRTUAL TABLE abc2 USING rtree_i32 $cols "
420db45212aSdan
421db45212aSdan# EVIDENCE-OF: R-06224-52418 In an RTREE_I32 virtual table, all columns
422db45212aSdan# have type affinity of INTEGER.
423db45212aSdan  do_execsql_test 1.$tn.8 {
424db45212aSdan    INSERT INTO abc2 VALUES('6.0', '6.0', '6.0', '6.0', '6.0');
425db45212aSdan    SELECT * FROM abc2
426db45212aSdan  } {6 6 6 6 6}
427db45212aSdan  do_execsql_test 1.$tn.9 {
428db45212aSdan    SELECT type FROM pragma_table_info('abc2') ORDER BY cid
429db45212aSdan  } {INT INT INT INT INT}
430db45212aSdan
431db45212aSdan
432db45212aSdan  do_execsql_test 1.$tn.10 {
433db45212aSdan    DROP TABLE abc;
434db45212aSdan    DROP TABLE abc2;
435db45212aSdan  }
436db45212aSdan}
43730918bfbSdan
4386962d78cSdan#-------------------------------------------------------------------------
4396962d78cSdan#-------------------------------------------------------------------------
4406962d78cSdan# Section 3.2 of documentation.
4416962d78cSdan#-------------------------------------------------------------------------
4426962d78cSdan#-------------------------------------------------------------------------
4436962d78cSdanset testprefix rtreedoc-4
4446962d78cSdanreset_db
4456962d78cSdan
4466962d78cSdan# EVIDENCE-OF: R-36195-31555 The usual INSERT, UPDATE, and DELETE
4476962d78cSdan# commands work on an R*Tree index just like on regular tables.
4486962d78cSdan#
4496962d78cSdan# Create a regular table and an rtree table. Perform INSERT, UPDATE and
4506962d78cSdan# DELETE operations, then observe that the contents of the two tables
4516962d78cSdan# are identical.
4526962d78cSdando_execsql_test 1.0 {
4536962d78cSdan  CREATE VIRTUAL TABLE rt USING rtree(id, x1, x2);
4546962d78cSdan  CREATE TABLE t1(id INTEGER PRIMARY KEY, x1 REAL, x2 REAL);
4556962d78cSdan}
4566962d78cSdanforeach {tn sql} {
4576962d78cSdan  1 "INSERT INTO %TBL% VALUES(5, 11,12)"
4586962d78cSdan  2 "INSERT INTO %TBL% VALUES(11, -11,14.5)"
4596962d78cSdan  3 "UPDATE %TBL% SET x1=-99 WHERE id=11"
4606962d78cSdan  4 "DELETE FROM %TBL% WHERE x2=14.5"
4616962d78cSdan  5 "DELETE FROM %TBL%"
4626962d78cSdan} {
4636962d78cSdan  set sql1 [string map {%TBL% rt} $sql]
4646962d78cSdan  set sql2 [string map {%TBL% t1} $sql]
4656962d78cSdan  do_execsql_test 1.$tn.0 $sql1
4666962d78cSdan  do_execsql_test 1.$tn.1 $sql2
4676962d78cSdan
4686962d78cSdan  set data1 [execsql {SELECT * FROM rt ORDER BY 1}]
4696962d78cSdan  set data2 [execsql {SELECT * FROM t1 ORDER BY 1}]
4706962d78cSdan
4716962d78cSdan  set res [expr {$data1==$data2}]
4726962d78cSdan  do_test 1.$tn.2 {set res} 1
4736962d78cSdan}
4746962d78cSdan
4756962d78cSdan# EVIDENCE-OF: R-56987-45305
4766962d78cSdando_execsql_test 2.0 {
4776962d78cSdan  CREATE VIRTUAL TABLE demo_index USING rtree(
4786962d78cSdan      id,              -- Integer primary key
4796962d78cSdan      minX, maxX,      -- Minimum and maximum X coordinate
4806962d78cSdan      minY, maxY       -- Minimum and maximum Y coordinate
4816962d78cSdan  );
4826962d78cSdan
4836962d78cSdan  INSERT INTO demo_index VALUES
4846962d78cSdan    (28215, -80.781227, -80.604706, 35.208813, 35.297367),
4856962d78cSdan    (28216, -80.957283, -80.840599, 35.235920, 35.367825),
4866962d78cSdan    (28217, -80.960869, -80.869431, 35.133682, 35.208233),
4876962d78cSdan    (28226, -80.878983, -80.778275, 35.060287, 35.154446),
4886962d78cSdan    (28227, -80.745544, -80.555382, 35.130215, 35.236916),
4896962d78cSdan    (28244, -80.844208, -80.841988, 35.223728, 35.225471),
4906962d78cSdan    (28262, -80.809074, -80.682938, 35.276207, 35.377747),
4916962d78cSdan    (28269, -80.851471, -80.735718, 35.272560, 35.407925),
4926962d78cSdan    (28270, -80.794983, -80.728966, 35.059872, 35.161823),
4936962d78cSdan    (28273, -80.994766, -80.875259, 35.074734, 35.172836),
4946962d78cSdan    (28277, -80.876793, -80.767586, 35.001709, 35.101063),
4956962d78cSdan    (28278, -81.058029, -80.956375, 35.044701, 35.223812),
4966962d78cSdan    (28280, -80.844208, -80.841972, 35.225468, 35.227203),
4976962d78cSdan    (28282, -80.846382, -80.844193, 35.223972, 35.225655);
4986962d78cSdan}
4996962d78cSdan
500a2fef2f0Sdan#-------------------------------------------------------------------------
501a2fef2f0Sdan#-------------------------------------------------------------------------
502a2fef2f0Sdan# Section 3.3 of documentation.
503a2fef2f0Sdan#-------------------------------------------------------------------------
504a2fef2f0Sdan#-------------------------------------------------------------------------
505a2fef2f0Sdanset testprefix rtreedoc-5
50630918bfbSdan
50772fb42d5Sdando_execsql_test 1.0 {
50872fb42d5Sdan  INSERT INTO demo_index
50972fb42d5Sdan    SELECT NULL, minX, maxX, minY+0.2, maxY+0.2 FROM demo_index;
51072fb42d5Sdan  INSERT INTO demo_index
51172fb42d5Sdan    SELECT NULL, minX+0.2, maxX+0.2, minY, maxY FROM demo_index;
51272fb42d5Sdan  INSERT INTO demo_index
51372fb42d5Sdan    SELECT NULL, minX, maxX, minY+0.4, maxY+0.4 FROM demo_index;
51472fb42d5Sdan  INSERT INTO demo_index
51572fb42d5Sdan    SELECT NULL, minX+0.4, maxX+0.4, minY, maxY FROM demo_index;
51672fb42d5Sdan  INSERT INTO demo_index
51772fb42d5Sdan    SELECT NULL, minX, maxX, minY+0.8, maxY+0.8 FROM demo_index;
51872fb42d5Sdan  INSERT INTO demo_index
51972fb42d5Sdan    SELECT NULL, minX+0.8, maxX+0.8, minY, maxY FROM demo_index;
52030918bfbSdan
52172fb42d5Sdan  SELECT count(*) FROM demo_index;
52272fb42d5Sdan} {896}
52372fb42d5Sdan
52472fb42d5Sdanproc do_vmstep_test {tn sql expr} {
52572fb42d5Sdan  execsql $sql
52672fb42d5Sdan  set step [db status vmstep]
52772fb42d5Sdan  do_test $tn.$step "expr {[subst $expr]}" 1
52872fb42d5Sdan}
52972fb42d5Sdan
53072fb42d5Sdan# EVIDENCE-OF: R-45880-07724 Any valid query will work against an R*Tree
53172fb42d5Sdan# index.
53272fb42d5Sdando_execsql_test 1.1.0 {
53372fb42d5Sdan  CREATE TABLE demo_tbl AS SELECT * FROM demo_index;
53472fb42d5Sdan}
53572fb42d5Sdanforeach {tn sql} {
53672fb42d5Sdan  1  {SELECT * FROM %TBL% ORDER BY 1}
53772fb42d5Sdan  2  {SELECT max(minX) FROM %TBL% ORDER BY 1}
53872fb42d5Sdan  3  {SELECT max(minX) FROM %TBL% GROUP BY round(minY) ORDER BY 1}
53972fb42d5Sdan} {
54072fb42d5Sdan  set sql1 [string map {%TBL% demo_index} $sql]
54172fb42d5Sdan  set sql2 [string map {%TBL% demo_tbl} $sql]
54272fb42d5Sdan
54372fb42d5Sdan  do_execsql_test 1.1.$tn $sql1 [execsql $sql2]
54472fb42d5Sdan}
54572fb42d5Sdan
54672fb42d5Sdan# EVIDENCE-OF: R-60814-18273 The R*Tree implementation just makes some
54772fb42d5Sdan# kinds of queries especially efficient.
54872fb42d5Sdan#
54972fb42d5Sdan# The second query is more efficient than the first.
55072fb42d5Sdando_vmstep_test 1.2.1 {SELECT * FROM demo_index WHERE +rowid=28269} {$step>2000}
55172fb42d5Sdando_vmstep_test 1.2.2 {SELECT * FROM demo_index WHERE rowid=28269} {$step<100}
55272fb42d5Sdan
55372fb42d5Sdan# EVIDENCE-OF: R-37800-50174 Queries against the primary key are
55472fb42d5Sdan# efficient: SELECT * FROM demo_index WHERE id=28269;
55572fb42d5Sdando_vmstep_test 2.2 { SELECT * FROM demo_index WHERE id=28269 } {$step < 100}
55672fb42d5Sdan
55772fb42d5Sdan# EVIDENCE-OF: R-35847-18866 The big reason for using an R*Tree is so
55872fb42d5Sdan# that you can efficiently do range queries against the coordinate
55972fb42d5Sdan# ranges.
56072fb42d5Sdan#
56172fb42d5Sdan# EVIDENCE-OF: R-49927-54202
56272fb42d5Sdando_vmstep_test 2.3 {
56372fb42d5Sdan  SELECT id FROM demo_index
56472fb42d5Sdan    WHERE minX<=-80.77470 AND maxX>=-80.77470
56572fb42d5Sdan    AND minY<=35.37785  AND maxY>=35.37785;
56672fb42d5Sdan} {$step < 100}
56772fb42d5Sdan
56872fb42d5Sdan# EVIDENCE-OF: R-12823-37176 The query above will quickly locate all
56972fb42d5Sdan# zipcodes that contain the SQLite main office in their bounding box,
57072fb42d5Sdan# even if the R*Tree contains many entries.
57172fb42d5Sdan#
57272fb42d5Sdando_execsql_test 2.4 {
57372fb42d5Sdan  SELECT id FROM demo_index
57472fb42d5Sdan    WHERE minX<=-80.77470 AND maxX>=-80.77470
57572fb42d5Sdan    AND minY<=35.37785  AND maxY>=35.37785;
57672fb42d5Sdan} {
57772fb42d5Sdan  28322 28269
57872fb42d5Sdan}
57972fb42d5Sdan
58072fb42d5Sdan# EVIDENCE-OF: R-07351-00257 For example, to find all zipcode bounding
58172fb42d5Sdan# boxes that overlap with the 28269 zipcode: SELECT A.id FROM demo_index
58272fb42d5Sdan# AS A, demo_index AS B WHERE A.maxX>=B.minX AND A.minX<=B.maxX
58372fb42d5Sdan# AND A.maxY>=B.minY AND A.minY<=B.maxY AND B.id=28269;
58472fb42d5Sdan#
58572fb42d5Sdan# Also check that it is efficient
58672fb42d5Sdan#
58772fb42d5Sdan# EVIDENCE-OF: R-39094-01937 This second query will find both 28269
58872fb42d5Sdan# entry (since every bounding box overlaps with itself) and also other
58972fb42d5Sdan# zipcode that is close enough to 28269 that their bounding boxes
59072fb42d5Sdan# overlap.
59172fb42d5Sdan#
59272fb42d5Sdan# 28269 is there in the result.
59372fb42d5Sdan#
59472fb42d5Sdando_vmstep_test 2.5.1 {
59572fb42d5Sdan  SELECT A.id FROM demo_index AS A, demo_index AS B
59672fb42d5Sdan    WHERE A.maxX>=B.minX AND A.minX<=B.maxX
59772fb42d5Sdan    AND A.maxY>=B.minY AND A.minY<=B.maxY
59872fb42d5Sdan    AND B.id=28269
59972fb42d5Sdan} {$step < 100}
60072fb42d5Sdando_execsql_test 2.5.2 {
60172fb42d5Sdan  SELECT A.id FROM demo_index AS A, demo_index AS B
60272fb42d5Sdan    WHERE A.maxX>=B.minX AND A.minX<=B.maxX
60372fb42d5Sdan    AND A.maxY>=B.minY AND A.minY<=B.maxY
60472fb42d5Sdan    AND B.id=28269;
60572fb42d5Sdan} {
60672fb42d5Sdan  28293 28216 28322 28286 28269
60772fb42d5Sdan  28215 28336 28262 28291 28320
60872fb42d5Sdan  28313 28298 28287
60972fb42d5Sdan}
61072fb42d5Sdan
61172fb42d5Sdan# EVIDENCE-OF: R-02723-34107 Note that it is not necessary for all
61272fb42d5Sdan# coordinates in an R*Tree index to be constrained in order for the
61372fb42d5Sdan# index search to be efficient.
61472fb42d5Sdan#
61572fb42d5Sdan# EVIDENCE-OF: R-22490-27246 One might, for example, want to query all
61672fb42d5Sdan# objects that overlap with the 35th parallel: SELECT id FROM demo_index
61772fb42d5Sdan# WHERE maxY>=35.0 AND minY<=35.0;
61872fb42d5Sdando_vmstep_test 2.6.1 {
61972fb42d5Sdan  SELECT id FROM demo_index
62072fb42d5Sdan   WHERE maxY>=35.0  AND minY<=35.0;
62172fb42d5Sdan} {$step < 100}
62272fb42d5Sdando_execsql_test 2.6.2 {
62372fb42d5Sdan  SELECT id FROM demo_index
62472fb42d5Sdan   WHERE maxY>=35.0  AND minY<=35.0;
62572fb42d5Sdan} {}
626a2fef2f0Sdan
627a2fef2f0Sdan
628a2fef2f0Sdan#-------------------------------------------------------------------------
629a2fef2f0Sdan#-------------------------------------------------------------------------
630a2fef2f0Sdan# Section 3.4 of documentation.
631a2fef2f0Sdan#-------------------------------------------------------------------------
632a2fef2f0Sdan#-------------------------------------------------------------------------
633a2fef2f0Sdanset testprefix rtreedoc-6
63472fb42d5Sdanreset_db
635a2fef2f0Sdan
636a2fef2f0Sdan# EVIDENCE-OF: R-08327-00674 By default, coordinates are stored in an
637a2fef2f0Sdan# R*Tree using 32-bit floating point values.
638a2fef2f0Sdan#
639f159323cSdan# EVIDENCE-OF: R-22000-53613 The default virtual table ("rtree") stores
640f159323cSdan# coordinates as single-precision (4-byte) floating point numbers.
641f159323cSdan#
642a2fef2f0Sdan# Show this by showing that rounding is consistent with 32-bit float
643a2fef2f0Sdan# rounding.
644a2fef2f0Sdando_execsql_test 1.0 {
645a2fef2f0Sdan  CREATE VIRTUAL TABLE rt USING rtree(id, a,b);
646a2fef2f0Sdan}
647a2fef2f0Sdando_execsql_test 1.1 {
648a2fef2f0Sdan  INSERT INTO rt VALUES(14, -1000000000000, 1000000000000);
649a2fef2f0Sdan  SELECT * FROM rt;
650a2fef2f0Sdan} {14 -1000000126976.0 1000000126976.0}
651a2fef2f0Sdan
652a2fef2f0Sdan# EVIDENCE-OF: R-39127-51288 When a coordinate cannot be exactly
653a2fef2f0Sdan# represented by a 32-bit floating point number, the lower-bound
654a2fef2f0Sdan# coordinates are rounded down and the upper-bound coordinates are
655a2fef2f0Sdan# rounded up.
656a2fef2f0Sdanforeach {tn val} {
657a2fef2f0Sdan  1 100000000000
658a2fef2f0Sdan  2 200000000000
659a2fef2f0Sdan  3 300000000000
660a2fef2f0Sdan  4 400000000000
661a2fef2f0Sdan
662a2fef2f0Sdan  5 -100000000000
663a2fef2f0Sdan  6 -200000000000
664a2fef2f0Sdan  7 -300000000000
665a2fef2f0Sdan  8 -400000000000
666a2fef2f0Sdan} {
667a2fef2f0Sdan  set val [expr $val]
668a2fef2f0Sdan  do_execsql_test 2.$tn.0 {DELETE FROM rt}
669a2fef2f0Sdan  do_execsql_test 2.$tn.1 {INSERT INTO rt VALUES(23, $val, $val)}
670a2fef2f0Sdan  do_execsql_test 2.$tn.2 {
671a2fef2f0Sdan    SELECT $val>=a, $val<=b, a!=b FROM rt
672a2fef2f0Sdan  } {1 1 1}
673a2fef2f0Sdan}
674a2fef2f0Sdan
675a2fef2f0Sdando_execsql_test 3.0 {
676a2fef2f0Sdan  DROP TABLE rt;
677a2fef2f0Sdan  CREATE VIRTUAL TABLE rt USING rtree(id, x1,x2, y1,y2);
678a2fef2f0Sdan}
679a2fef2f0Sdan
680a2fef2f0Sdan# EVIDENCE-OF: R-45870-62834 Thus, bounding boxes might be slightly
681a2fef2f0Sdan# larger than specified, but will never be any smaller.
682a2fef2f0Sdanforeach {tn x1 x2 y1 y2} {
683a2fef2f0Sdan  1 100000000000 200000000000 300000000000 400000000000
684a2fef2f0Sdan} {
685a2fef2f0Sdan  set val [expr $val]
686a2fef2f0Sdan  do_execsql_test 3.$tn.0 {DELETE FROM rt}
687a2fef2f0Sdan  do_execsql_test 3.$tn.1 {INSERT INTO rt VALUES(23, $x1, $x2, $y1, $y2)}
688a2fef2f0Sdan  do_execsql_test 3.$tn.2 {
689a2fef2f0Sdan    SELECT (x2-x1)*(y2-y1) >= ($x2-$x1)*($y2-$y1) FROM rt
690a2fef2f0Sdan  } {1}
691a2fef2f0Sdan}
692a2fef2f0Sdan
693a2fef2f0Sdan#-------------------------------------------------------------------------
694a2fef2f0Sdan#-------------------------------------------------------------------------
695a2fef2f0Sdan# Section 3.5 of documentation.
696a2fef2f0Sdan#-------------------------------------------------------------------------
697a2fef2f0Sdan#-------------------------------------------------------------------------
698a2fef2f0Sdanset testprefix rtreedoc-7
699a2fef2f0Sdanreset_db
700a2fef2f0Sdan
701a2fef2f0Sdan# EVIDENCE-OF: R-55979-39402 It is the nature of the Guttman R-Tree
702a2fef2f0Sdan# algorithm that any write might radically restructure the tree, and in
703a2fef2f0Sdan# the process change the scan order of the nodes.
704a2fef2f0Sdan#
705a2fef2f0Sdan# In the test below, the INSERT marked "THIS INSERT!!" does not affect
706a2fef2f0Sdan# the results of queries with an ORDER BY, but does affect the results
707a2fef2f0Sdan# of one without an ORDER BY. Therefore the INSERT changed the scan
708a2fef2f0Sdan# order.
709a2fef2f0Sdando_execsql_test 1.0 {
710a2fef2f0Sdan  CREATE VIRTUAL TABLE rt USING rtree(id, minX, maxX);
711a2fef2f0Sdan  WITH s(i) AS (
712a2fef2f0Sdan    SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<51
713a2fef2f0Sdan  )
714a2fef2f0Sdan  INSERT INTO rt SELECT NULL, i%10, (i%10)+5 FROM s
715a2fef2f0Sdan}
716a2fef2f0Sdando_execsql_test 1.1 { SELECT count(*) FROM rt_node } 1
717a2fef2f0Sdando_test 1.2 {
718a2fef2f0Sdan  set res1 [db eval {SELECT * FROM rt WHERE maxX < 30}]
719a2fef2f0Sdan  set res1o [db eval {SELECT * FROM rt WHERE maxX < 30 ORDER BY +id}]
720a2fef2f0Sdan
721a2fef2f0Sdan  db eval { INSERT INTO rt VALUES(NULL, 50, 50) }   ;# THIS INSERT!!
722a2fef2f0Sdan
723a2fef2f0Sdan  set res2 [db eval {SELECT * FROM rt WHERE maxX < 30}]
724a2fef2f0Sdan  set res2o [db eval {SELECT * FROM rt WHERE maxX < 30 ORDER BY +id}]
725a2fef2f0Sdan  list [expr {$res1==$res2}] [expr {$res1o==$res2o}]
726a2fef2f0Sdan} {0 1}
727a2fef2f0Sdan
728a2fef2f0Sdando_execsql_test 1.3 { SELECT count(*) FROM rt_node } 3
729a2fef2f0Sdan
730a2fef2f0Sdan# EVIDENCE-OF: R-00683-48865 For this reason, it is not generally
731a2fef2f0Sdan# possible to modify the R-Tree in the middle of a query of the R-Tree.
732a2fef2f0Sdan# Attempts to do so will fail with a SQLITE_LOCKED "database table is
733a2fef2f0Sdan# locked" error.
734a2fef2f0Sdan#
735a2fef2f0Sdan# SQLITE_LOCKED==6
736a2fef2f0Sdan#
737a2fef2f0Sdando_test 1.4 {
738a2fef2f0Sdan  set nCnt 3
739a2fef2f0Sdan  db eval { SELECT * FROM rt WHERE minX>0 AND maxX<12 } {
740a2fef2f0Sdan    incr nCnt -1
741a2fef2f0Sdan    if {$nCnt==0} {
742a2fef2f0Sdan      set rc [catch {db eval {
743a2fef2f0Sdan        INSERT INTO rt VALUES(NULL, 51, 51);
744a2fef2f0Sdan      }} msg]
745a2fef2f0Sdan      set errorcode [db errorcode]
746a2fef2f0Sdan      break
747a2fef2f0Sdan    }
748a2fef2f0Sdan  }
749a2fef2f0Sdan
750a2fef2f0Sdan  list $errorcode $rc $msg
751a2fef2f0Sdan} {6 1 {database table is locked}}
752a2fef2f0Sdan
753a2fef2f0Sdan# EVIDENCE-OF: R-19740-29710 So, for example, suppose an application
754a2fef2f0Sdan# runs one query against an R-Tree like this: SELECT id FROM demo_index
755a2fef2f0Sdan# WHERE maxY>=35.0 AND minY<=35.0; Then for each "id" value
756a2fef2f0Sdan# returned, suppose the application creates an UPDATE statement like the
757a2fef2f0Sdan# following and binds the "id" value returned against the "?1"
758a2fef2f0Sdan# parameter: UPDATE demo_index SET maxY=maxY+0.5 WHERE id=?1;
759a2fef2f0Sdan#
760a2fef2f0Sdan# EVIDENCE-OF: R-52919-32711 Then the UPDATE might fail with an
761a2fef2f0Sdan# SQLITE_LOCKED error.
762a2fef2f0Sdando_execsql_test 2.0 {
763a2fef2f0Sdan  CREATE VIRTUAL TABLE demo_index USING rtree(
764a2fef2f0Sdan      id,              -- Integer primary key
765a2fef2f0Sdan      minX, maxX,      -- Minimum and maximum X coordinate
766a2fef2f0Sdan      minY, maxY       -- Minimum and maximum Y coordinate
767a2fef2f0Sdan  );
768a2fef2f0Sdan  INSERT INTO demo_index VALUES
769a2fef2f0Sdan    (28215, -80.781227, -80.604706, 35.208813, 35.297367),
770a2fef2f0Sdan    (28216, -80.957283, -80.840599, 35.235920, 35.367825),
771a2fef2f0Sdan    (28217, -80.960869, -80.869431, 35.133682, 35.208233),
772a2fef2f0Sdan    (28226, -80.878983, -80.778275, 35.060287, 35.154446);
773a2fef2f0Sdan}
774a2fef2f0Sdando_test 2.1 {
775a2fef2f0Sdan  db eval { SELECT id FROM demo_index WHERE maxY>=35.0  AND minY<=35.0 } {
776a2fef2f0Sdan    set rc [catch {
777a2fef2f0Sdan      db eval { UPDATE demo_index SET maxY=maxY+0.5 WHERE id=$id }
778a2fef2f0Sdan    } msg]
779a2fef2f0Sdan    set errorcode [db errorcode]
780a2fef2f0Sdan    break
781a2fef2f0Sdan  }
782a2fef2f0Sdan  list $errorcode $rc $msg
783a2fef2f0Sdan} {6 1 {database table is locked}}
784a2fef2f0Sdan
785a2fef2f0Sdan# EVIDENCE-OF: R-32604-49843 Ordinary tables in SQLite are able to read
786a2fef2f0Sdan# and write at the same time.
787a2fef2f0Sdan#
788a2fef2f0Sdando_execsql_test 3.0 {
789a2fef2f0Sdan  CREATE TABLE x1(a INTEGER PRIMARY KEY, b, c);
790a2fef2f0Sdan  INSERT INTO x1 VALUES(1, 1, 1);
791a2fef2f0Sdan  INSERT INTO x1 VALUES(2, 2, 2);
792a2fef2f0Sdan  INSERT INTO x1 VALUES(3, 3, 3);
793a2fef2f0Sdan  INSERT INTO x1 VALUES(4, 4, 4);
794a2fef2f0Sdan}
795a2fef2f0Sdando_test 3.1 {
796*dcf10a1aSdrh  unset -nocomplain res
797a2fef2f0Sdan  set res [list]
798a2fef2f0Sdan  db eval { SELECT * FROM x1 } {
799a2fef2f0Sdan    lappend res $a $b $c
800a2fef2f0Sdan    switch -- $a {
801a2fef2f0Sdan      1 {
802a2fef2f0Sdan        db eval { INSERT INTO x1 VALUES(5, 5, 5) }
803a2fef2f0Sdan      }
804a2fef2f0Sdan      2 {
805a2fef2f0Sdan        db eval { UPDATE x1 SET c=20 WHERE a=2 }
806a2fef2f0Sdan      }
807a2fef2f0Sdan      3 {
808a2fef2f0Sdan        db eval { DELETE FROM x1 WHERE c IN (3,4) }
809a2fef2f0Sdan      }
810a2fef2f0Sdan    }
811a2fef2f0Sdan  }
812a2fef2f0Sdan  set res
813a2fef2f0Sdan} {1 1 1 2 2 2 3 3 3 5 5 5}
814a2fef2f0Sdando_execsql_test 3.2 {
815a2fef2f0Sdan  SELECT * FROM x1
816a2fef2f0Sdan} {1 1 1  2 2 20  5 5 5}
817a2fef2f0Sdan
818a2fef2f0Sdan# EVIDENCE-OF: R-06177-00576 And R-Tree can appear to read and write at
819a2fef2f0Sdan# the same time in some circumstances, if it can figure out how to
820a2fef2f0Sdan# reliably run the query to completion before starting the update.
821a2fef2f0Sdan#
822a2fef2f0Sdan# In 8.2, it can, it 8.1, it cannot.
823a2fef2f0Sdando_test 8.1 {
824a2fef2f0Sdan  db eval { SELECT * FROM rt } {
825a2fef2f0Sdan    set rc [catch { db eval { INSERT INTO rt VALUES(53,53,53) } } msg]
826a2fef2f0Sdan    break;
827a2fef2f0Sdan  }
828a2fef2f0Sdan  list $rc $msg
829a2fef2f0Sdan} {1 {database table is locked}}
830a2fef2f0Sdando_test 8.2 {
831a2fef2f0Sdan  db eval { SELECT * FROM rt ORDER BY +id } {
832a2fef2f0Sdan    set rc [catch { db eval { INSERT INTO rt VALUES(53,53,53) } } msg]
833a2fef2f0Sdan    break
834a2fef2f0Sdan  }
835a2fef2f0Sdan  list $rc $msg
836a2fef2f0Sdan} {0 {}}
837a2fef2f0Sdan
838a2fef2f0Sdan#-------------------------------------------------------------------------
839a2fef2f0Sdan#-------------------------------------------------------------------------
840a2fef2f0Sdan# Section 4 of documentation.
841a2fef2f0Sdan#-------------------------------------------------------------------------
842a2fef2f0Sdan#-------------------------------------------------------------------------
843a2fef2f0Sdanset testprefix rtreedoc-8
84472fb42d5Sdanreset_db
845a2fef2f0Sdan
846f159323cSdan# EVIDENCE-OF: R-21062-30088 For the example above, one might create an
847f159323cSdan# auxiliary table as follows: CREATE TABLE demo_data( id INTEGER PRIMARY
848f159323cSdan# KEY, -- primary key objname TEXT, -- name of the object objtype TEXT,
849f159323cSdan# -- object type boundary BLOB -- detailed boundary of object );
850f159323cSdan#
851f159323cSdan# One might.
852f159323cSdan#
853f159323cSdando_execsql_test 1.0 {
854f159323cSdan  CREATE TABLE demo_data(
855f159323cSdan      id INTEGER PRIMARY KEY,  -- primary key
856f159323cSdan      objname TEXT,            -- name of the object
857f159323cSdan      objtype TEXT,            -- object type
858f159323cSdan      boundary BLOB            -- detailed boundary of object
859f159323cSdan  );
860f159323cSdan}
861f159323cSdan
86272fb42d5Sdando_execsql_test 1.1 {
86372fb42d5Sdan  CREATE VIRTUAL TABLE demo_index USING rtree(
86472fb42d5Sdan      id,              -- Integer primary key
86572fb42d5Sdan      minX, maxX,      -- Minimum and maximum X coordinate
86672fb42d5Sdan      minY, maxY       -- Minimum and maximum Y coordinate
86772fb42d5Sdan  );
86872fb42d5Sdan
86972fb42d5Sdan  INSERT INTO demo_index VALUES
87072fb42d5Sdan    (28215, -80.781227, -80.604706, 35.208813, 35.297367),
87172fb42d5Sdan    (28216, -80.957283, -80.840599, 35.235920, 35.367825),
87272fb42d5Sdan    (28217, -80.960869, -80.869431, 35.133682, 35.208233),
87372fb42d5Sdan    (28226, -80.878983, -80.778275, 35.060287, 35.154446),
87472fb42d5Sdan    (28227, -80.745544, -80.555382, 35.130215, 35.236916),
87572fb42d5Sdan    (28244, -80.844208, -80.841988, 35.223728, 35.225471),
87672fb42d5Sdan    (28262, -80.809074, -80.682938, 35.276207, 35.377747),
87772fb42d5Sdan    (28269, -80.851471, -80.735718, 35.272560, 35.407925),
87872fb42d5Sdan    (28270, -80.794983, -80.728966, 35.059872, 35.161823),
87972fb42d5Sdan    (28273, -80.994766, -80.875259, 35.074734, 35.172836),
88072fb42d5Sdan    (28277, -80.876793, -80.767586, 35.001709, 35.101063),
88172fb42d5Sdan    (28278, -81.058029, -80.956375, 35.044701, 35.223812),
88272fb42d5Sdan    (28280, -80.844208, -80.841972, 35.225468, 35.227203),
88372fb42d5Sdan    (28282, -80.846382, -80.844193, 35.223972, 35.225655);
88472fb42d5Sdan
88572fb42d5Sdan  INSERT INTO demo_index
88672fb42d5Sdan    SELECT NULL, minX, maxX, minY+0.2, maxY+0.2 FROM demo_index;
88772fb42d5Sdan  INSERT INTO demo_index
88872fb42d5Sdan    SELECT NULL, minX+0.2, maxX+0.2, minY, maxY FROM demo_index;
88972fb42d5Sdan  INSERT INTO demo_index
89072fb42d5Sdan    SELECT NULL, minX, maxX, minY+0.4, maxY+0.4 FROM demo_index;
89172fb42d5Sdan  INSERT INTO demo_index
89272fb42d5Sdan    SELECT NULL, minX+0.4, maxX+0.4, minY, maxY FROM demo_index;
89372fb42d5Sdan  INSERT INTO demo_index
89472fb42d5Sdan    SELECT NULL, minX, maxX, minY+0.8, maxY+0.8 FROM demo_index;
89572fb42d5Sdan  INSERT INTO demo_index
89672fb42d5Sdan    SELECT NULL, minX+0.8, maxX+0.8, minY, maxY FROM demo_index;
89772fb42d5Sdan
89872fb42d5Sdan  INSERT INTO demo_data(id) SELECT id FROM demo_index;
89972fb42d5Sdan
90072fb42d5Sdan  SELECT count(*) FROM demo_index;
90172fb42d5Sdan} {896}
90272fb42d5Sdan
90372fb42d5Sdanset ::contained_in 0
90472fb42d5Sdanproc contained_in {args} {incr ::contained_in ; return 0}
90572fb42d5Sdandb func contained_in contained_in
90672fb42d5Sdan
90701ed72f2Sdan# EVIDENCE-OF: R-32671-43888 Then an efficient way to find the specific
90801ed72f2Sdan# ZIP code for the main SQLite office would be to run a query like this:
90901ed72f2Sdan# SELECT objname FROM demo_data, demo_index WHERE
91001ed72f2Sdan# demo_data.id=demo_index.id AND contained_in(demo_data.boundary,
91101ed72f2Sdan# 35.37785, -80.77470) AND minX<=-80.77470 AND maxX>=-80.77470 AND
91201ed72f2Sdan# minY<=35.37785 AND maxY>=35.37785;
91372fb42d5Sdando_vmstep_test 1.2 {
91472fb42d5Sdan  SELECT objname FROM demo_data, demo_index
91572fb42d5Sdan    WHERE demo_data.id=demo_index.id
91672fb42d5Sdan    AND contained_in(demo_data.boundary, 35.37785, -80.77470)
91772fb42d5Sdan    AND minX<=-80.77470 AND maxX>=-80.77470
91872fb42d5Sdan    AND minY<=35.37785  AND maxY>=35.37785;
91972fb42d5Sdan} {$step<100}
92072fb42d5Sdanset ::contained_in1 $::contained_in
92172fb42d5Sdan
92272fb42d5Sdan# EVIDENCE-OF: R-32761-23915 One would get the same answer without the
92372fb42d5Sdan# use of the R*Tree index using the following simpler query: SELECT
92472fb42d5Sdan# objname FROM demo_data WHERE contained_in(demo_data.boundary,
92572fb42d5Sdan# 35.37785, -80.77470);
92672fb42d5Sdanset ::contained_in 0
92772fb42d5Sdando_vmstep_test 1.3 {
92872fb42d5Sdan  SELECT objname FROM demo_data
92972fb42d5Sdan    WHERE contained_in(demo_data.boundary, 35.37785, -80.77470);
93091f62153Sdan} {$step>3200}
93172fb42d5Sdan
93272fb42d5Sdan# EVIDENCE-OF: R-40261-32799 The problem with this latter query is that
93372fb42d5Sdan# it must apply the contained_in() function to all entries in the
93472fb42d5Sdan# demo_data table.
93572fb42d5Sdan#
93672fb42d5Sdan# 896 of them, IIRC.
93772fb42d5Sdando_test 1.4 {
93872fb42d5Sdan  set ::contained_in
93972fb42d5Sdan} 896
94072fb42d5Sdan
94172fb42d5Sdan# EVIDENCE-OF: R-24212-52761 The use of the R*Tree in the penultimate
94272fb42d5Sdan# query reduces the number of calls to contained_in() function to a
94372fb42d5Sdan# small subset of the entire table.
94472fb42d5Sdan#
94572fb42d5Sdan# 2 is a small subset of 896.
94672fb42d5Sdan#
94772fb42d5Sdan# EVIDENCE-OF: R-39057-63901 The R*Tree index did not find the exact
94872fb42d5Sdan# answer itself, it merely limited the search space.
94972fb42d5Sdan#
95072fb42d5Sdan# contained_in() filtered out those 2 rows.
95172fb42d5Sdando_test 1.5 {
95272fb42d5Sdan  set ::contained_in1
95372fb42d5Sdan} {2}
95472fb42d5Sdan
95572fb42d5Sdan
956f159323cSdan#-------------------------------------------------------------------------
957f159323cSdan#-------------------------------------------------------------------------
958f159323cSdan# Section 4.1 of documentation.
959f159323cSdan#-------------------------------------------------------------------------
960f159323cSdan#-------------------------------------------------------------------------
961f159323cSdanset testprefix rtreedoc-9
962f159323cSdanreset_db
963f159323cSdan
964f159323cSdan# EVIDENCE-OF: R-46566-43213 Beginning with SQLite version 3.24.0
965f159323cSdan# (2018-06-04), r-tree tables can have auxiliary columns that store
966f159323cSdan# arbitrary data. Auxiliary columns can be used in place of secondary
967f159323cSdan# tables such as "demo_data".
968f159323cSdan#
969f159323cSdan# EVIDENCE-OF: R-41287-48160 Auxiliary columns are marked with a "+"
970f159323cSdan# symbol before the column name.
971f159323cSdan#
972f159323cSdan# This interface cannot conveniently be used to prove anything about
973f159323cSdan# versions of SQLite prior to 3.24.0.
974f159323cSdan#
975f159323cSdando_execsql_test 1.0 {
976f159323cSdan  CREATE VIRTUAL TABLE rta USING rtree(
977f159323cSdan    id, u1,u2,  v1,v2,   +aux
978f159323cSdan  );
979f159323cSdan
980f159323cSdan  INSERT INTO rta(aux) VALUES(NULL);
981f159323cSdan  INSERT INTO rta(aux) VALUES(45);
982f159323cSdan  INSERT INTO rta(aux) VALUES(22.3);
983f159323cSdan  INSERT INTO rta(aux) VALUES('hello');
984f159323cSdan  INSERT INTO rta(aux) VALUES(X'ABCD');
985f159323cSdan
986f159323cSdan  SELECT typeof(aux), quote(aux) FROM rta;
987f159323cSdan} {
988f159323cSdan  null NULL
989f159323cSdan  integer 45
990f159323cSdan  real 22.3
991f159323cSdan  text 'hello'
992f159323cSdan  blob X'ABCD'
993f159323cSdan}
994f159323cSdan
995f159323cSdan# EVIDENCE-OF: R-30514-26093 Auxiliary columns must come after all of
996f159323cSdan# the coordinate boundary columns.
997f159323cSdanforeach {tn cols} {
998f159323cSdan  1 "id x1,x2, +extra,  y1,y2"
999f159323cSdan  2 "extra, +id x1,x2, y1,y2"
1000f159323cSdan  3 "id, x1,+x2, extra, y1,y2"
1001f159323cSdan} {
1002f159323cSdan  do_catchsql_test 2.$tn "
1003f159323cSdan    CREATE VIRTUAL TABLE rrr USING rtree($cols)
1004f159323cSdan  " {1 {Auxiliary rtree columns must be last}}
1005f159323cSdan}
1006f159323cSdando_catchsql_test 3.0 {
1007f159323cSdan  CREATE VIRTUAL TABLE rrr USING rtree(+id, extra, x1, x2);
1008f159323cSdan} {1 {near "+": syntax error}}
1009f159323cSdan
1010f159323cSdan# EVIDENCE-OF: R-01280-03635 An RTREE table can have no more than 100
1011f159323cSdan# columns total. In other words, the count of columns including the
1012f159323cSdan# integer primary key column, the coordinate boundary columns, and all
1013f159323cSdan# auxiliary columns must be 100 or less.
1014f159323cSdando_catchsql_test 3.1 {
1015f159323cSdan  CREATE VIRTUAL TABLE r1 USING rtree(intid, u1,u2,
1016f159323cSdan    +c00, +c01, +c02, +c03, +c04, +c05, +c06, +c07, +c08, +c09,
1017f159323cSdan    +c10, +c11, +c12, +c13, +c14, +c15, +c16, +c17, +c18, +c19,
1018f159323cSdan    +c20, +c21, +c22, +c23, +c24, +c25, +c26, +c27, +c28, +c29,
1019f159323cSdan    +c30, +c31, +c32, +c33, +c34, +c35, +c36, +c37, +c38, +c39,
1020f159323cSdan    +c40, +c41, +c42, +c43, +c44, +c45, +c46, +c47, +c48, +c49,
1021f159323cSdan    +c50, +c51, +c52, +c53, +c54, +c55, +c56, +c57, +c58, +c59,
1022f159323cSdan    +c60, +c61, +c62, +c63, +c64, +c65, +c66, +c67, +c68, +c69,
1023f159323cSdan    +c70, +c71, +c72, +c73, +c74, +c75, +c76, +c77, +c78, +c79,
1024f159323cSdan    +c80, +c81, +c82, +c83, +c84, +c85, +c86, +c87, +c88, +c89,
1025f159323cSdan    +c90, +c91, +c92, +c93, +c94, +c95, +c96
1026f159323cSdan  );
1027f159323cSdan} {0 {}}
1028f159323cSdando_catchsql_test 3.2 {
1029f159323cSdan  DROP TABLE r1;
1030f159323cSdan  CREATE VIRTUAL TABLE r1 USING rtree(intid, u1,u2,
1031f159323cSdan    +c00, +c01, +c02, +c03, +c04, +c05, +c06, +c07, +c08, +c09,
1032f159323cSdan    +c10, +c11, +c12, +c13, +c14, +c15, +c16, +c17, +c18, +c19,
1033f159323cSdan    +c20, +c21, +c22, +c23, +c24, +c25, +c26, +c27, +c28, +c29,
1034f159323cSdan    +c30, +c31, +c32, +c33, +c34, +c35, +c36, +c37, +c38, +c39,
1035f159323cSdan    +c40, +c41, +c42, +c43, +c44, +c45, +c46, +c47, +c48, +c49,
1036f159323cSdan    +c50, +c51, +c52, +c53, +c54, +c55, +c56, +c57, +c58, +c59,
1037f159323cSdan    +c60, +c61, +c62, +c63, +c64, +c65, +c66, +c67, +c68, +c69,
1038f159323cSdan    +c70, +c71, +c72, +c73, +c74, +c75, +c76, +c77, +c78, +c79,
1039f159323cSdan    +c80, +c81, +c82, +c83, +c84, +c85, +c86, +c87, +c88, +c89,
1040f159323cSdan    +c90, +c91, +c92, +c93, +c94, +c95, +c96, +c97
1041f159323cSdan  );
1042f159323cSdan} {1 {Too many columns for an rtree table}}
1043f159323cSdando_catchsql_test 3.3 {
1044f159323cSdan  CREATE VIRTUAL TABLE r1 USING rtree(intid, u1,u2, v1,v2,
1045f159323cSdan    +c00, +c01, +c02, +c03, +c04, +c05, +c06, +c07, +c08, +c09,
1046f159323cSdan    +c10, +c11, +c12, +c13, +c14, +c15, +c16, +c17, +c18, +c19,
1047f159323cSdan    +c20, +c21, +c22, +c23, +c24, +c25, +c26, +c27, +c28, +c29,
1048f159323cSdan    +c30, +c31, +c32, +c33, +c34, +c35, +c36, +c37, +c38, +c39,
1049f159323cSdan    +c40, +c41, +c42, +c43, +c44, +c45, +c46, +c47, +c48, +c49,
1050f159323cSdan    +c50, +c51, +c52, +c53, +c54, +c55, +c56, +c57, +c58, +c59,
1051f159323cSdan    +c60, +c61, +c62, +c63, +c64, +c65, +c66, +c67, +c68, +c69,
1052f159323cSdan    +c70, +c71, +c72, +c73, +c74, +c75, +c76, +c77, +c78, +c79,
1053f159323cSdan    +c80, +c81, +c82, +c83, +c84, +c85, +c86, +c87, +c88, +c89,
1054f159323cSdan    +c90, +c91, +c92, +c93, +c94,
1055f159323cSdan  );
1056f159323cSdan} {0 {}}
1057f159323cSdando_catchsql_test 3.4 {
1058f159323cSdan  DROP TABLE r1;
1059f159323cSdan  CREATE VIRTUAL TABLE r1 USING rtree(intid, u1,u2, v1,v2,
1060f159323cSdan    +c00, +c01, +c02, +c03, +c04, +c05, +c06, +c07, +c08, +c09,
1061f159323cSdan    +c10, +c11, +c12, +c13, +c14, +c15, +c16, +c17, +c18, +c19,
1062f159323cSdan    +c20, +c21, +c22, +c23, +c24, +c25, +c26, +c27, +c28, +c29,
1063f159323cSdan    +c30, +c31, +c32, +c33, +c34, +c35, +c36, +c37, +c38, +c39,
1064f159323cSdan    +c40, +c41, +c42, +c43, +c44, +c45, +c46, +c47, +c48, +c49,
1065f159323cSdan    +c50, +c51, +c52, +c53, +c54, +c55, +c56, +c57, +c58, +c59,
1066f159323cSdan    +c60, +c61, +c62, +c63, +c64, +c65, +c66, +c67, +c68, +c69,
1067f159323cSdan    +c70, +c71, +c72, +c73, +c74, +c75, +c76, +c77, +c78, +c79,
1068f159323cSdan    +c80, +c81, +c82, +c83, +c84, +c85, +c86, +c87, +c88, +c89,
1069f159323cSdan    +c90, +c91, +c92, +c93, +c94, +c95,
1070f159323cSdan  );
1071f159323cSdan} {1 {Too many columns for an rtree table}}
1072f159323cSdan
1073f159323cSdan# EVIDENCE-OF: R-05552-15084
1074f159323cSdando_execsql_test 4.0 {
1075f159323cSdan  CREATE VIRTUAL TABLE demo_index2 USING rtree(
1076f159323cSdan      id,              -- Integer primary key
1077f159323cSdan      minX, maxX,      -- Minimum and maximum X coordinate
1078f159323cSdan      minY, maxY,      -- Minimum and maximum Y coordinate
1079f159323cSdan      +objname TEXT,   -- name of the object
1080f159323cSdan      +objtype TEXT,   -- object type
1081f159323cSdan      +boundary BLOB   -- detailed boundary of object
1082f159323cSdan  );
1083f159323cSdan}
1084f159323cSdando_execsql_test 4.1 {
1085f159323cSdan  CREATE VIRTUAL TABLE demo_index USING rtree(
1086f159323cSdan      id,              -- Integer primary key
1087f159323cSdan      minX, maxX,      -- Minimum and maximum X coordinate
1088f159323cSdan      minY, maxY       -- Minimum and maximum Y coordinate
1089f159323cSdan  );
1090f159323cSdan  CREATE TABLE demo_data(
1091f159323cSdan      id INTEGER PRIMARY KEY,  -- primary key
1092f159323cSdan      objname TEXT,            -- name of the object
1093f159323cSdan      objtype TEXT,            -- object type
1094f159323cSdan      boundary BLOB            -- detailed boundary of object
1095f159323cSdan  );
1096f159323cSdan
1097f159323cSdan  INSERT INTO demo_index2(id) VALUES(1);
1098f159323cSdan  INSERT INTO demo_index(id) VALUES(1);
1099f159323cSdan  INSERT INTO demo_data(id) VALUES(1);
1100f159323cSdan}
1101f159323cSdando_test 4.2 {
1102f159323cSdan  catch { array unset R }
1103f159323cSdan  db eval {SELECT * FROM demo_index2} R { set r1 [array names R] }
1104f159323cSdan  catch { array unset R }
1105f159323cSdan  db eval {SELECT * FROM demo_index NATURAL JOIN demo_data } R {
1106f159323cSdan    set r2 [array names R]
1107f159323cSdan  }
1108f159323cSdan  expr {$r1==$r2}
1109f159323cSdan} {1}
1110f159323cSdan
111172fb42d5Sdan# EVIDENCE-OF: R-26099-32169 SELECT objname FROM demo_index2 WHERE
111272fb42d5Sdan# contained_in(boundary, 35.37785, -80.77470) AND minX<=-80.77470 AND
111372fb42d5Sdan# maxX>=-80.77470 AND minY<=35.37785 AND maxY>=35.37785;
111472fb42d5Sdando_execsql_test 4.3.1 {
111572fb42d5Sdan  DELETE FROM demo_index2;
111672fb42d5Sdan  INSERT INTO demo_index2(id,minX,maxX,minY,maxY) VALUES
111772fb42d5Sdan    (28215, -80.781227, -80.604706, 35.208813, 35.297367),
111872fb42d5Sdan    (28216, -80.957283, -80.840599, 35.235920, 35.367825),
111972fb42d5Sdan    (28217, -80.960869, -80.869431, 35.133682, 35.208233),
112072fb42d5Sdan    (28226, -80.878983, -80.778275, 35.060287, 35.154446),
112172fb42d5Sdan    (28227, -80.745544, -80.555382, 35.130215, 35.236916),
112272fb42d5Sdan    (28244, -80.844208, -80.841988, 35.223728, 35.225471),
112372fb42d5Sdan    (28262, -80.809074, -80.682938, 35.276207, 35.377747),
112472fb42d5Sdan    (28269, -80.851471, -80.735718, 35.272560, 35.407925),
112572fb42d5Sdan    (28270, -80.794983, -80.728966, 35.059872, 35.161823),
112672fb42d5Sdan    (28273, -80.994766, -80.875259, 35.074734, 35.172836),
112772fb42d5Sdan    (28277, -80.876793, -80.767586, 35.001709, 35.101063),
112872fb42d5Sdan    (28278, -81.058029, -80.956375, 35.044701, 35.223812),
112972fb42d5Sdan    (28280, -80.844208, -80.841972, 35.225468, 35.227203),
113072fb42d5Sdan    (28282, -80.846382, -80.844193, 35.223972, 35.225655);
113172fb42d5Sdan}
113272fb42d5Sdanset ::contained_in 0
113372fb42d5Sdanproc contained_in {args} {
113472fb42d5Sdan  incr ::contained_in
113572fb42d5Sdan  return 0
113672fb42d5Sdan}
113772fb42d5Sdandb func contained_in contained_in
113872fb42d5Sdando_execsql_test 4.3.2 {
113972fb42d5Sdan  SELECT objname FROM demo_index2
114072fb42d5Sdan    WHERE contained_in(boundary, 35.37785, -80.77470)
114172fb42d5Sdan    AND minX<=-80.77470 AND maxX>=-80.77470
114272fb42d5Sdan    AND minY<=35.37785  AND maxY>=35.37785;
114372fb42d5Sdan}
114472fb42d5Sdando_test 4.3.3 {
114572fb42d5Sdan  # Function invoked only once because r-tree filtering happened first.
114672fb42d5Sdan  set ::contained_in
114772fb42d5Sdan} 1
114872fb42d5Sdanset ::contained_in 0
114972fb42d5Sdando_execsql_test 4.3.4 {
115072fb42d5Sdan  SELECT objname FROM demo_index2
115172fb42d5Sdan    WHERE contained_in(boundary, 35.37785, -80.77470)
115272fb42d5Sdan}
115372fb42d5Sdando_test 4.3.3 {
115472fb42d5Sdan  # Function invoked 14 times because no r-tree filtering. Inefficient.
115572fb42d5Sdan  set ::contained_in
115672fb42d5Sdan} 14
115772fb42d5Sdan
1158f159323cSdan#-------------------------------------------------------------------------
1159f159323cSdan#-------------------------------------------------------------------------
1160f159323cSdan# Section 4.1.1 of documentation.
1161f159323cSdan#-------------------------------------------------------------------------
1162f159323cSdan#-------------------------------------------------------------------------
1163f159323cSdanset testprefix rtreedoc-9
1164f159323cSdanreset_db
1165f159323cSdan
1166f159323cSdan# EVIDENCE-OF: R-24021-02490 For auxiliary columns, only the name of the
1167f159323cSdan# column matters. The type affinity is ignored.
1168f159323cSdan#
1169f159323cSdan# EVIDENCE-OF: R-39906-44154 Constraints such as NOT NULL, UNIQUE,
1170f159323cSdan# REFERENCES, or CHECK are also ignored.
1171f159323cSdando_execsql_test 1.0 { PRAGMA foreign_keys = on }
1172f159323cSdanforeach {tn auxcol nm} {
1173f159323cSdan  1 "+extra INTEGER" extra
1174f159323cSdan  2 "+extra TEXT"    extra
1175f159323cSdan  3 "+extra BLOB"    extra
1176f159323cSdan  4 "+extra REAL"    extra
1177f159323cSdan
1178f159323cSdan  5 "+col NOT NULL"                 col
1179f159323cSdan  6 "+col CHECK (col IS NOT NULL)"  col
1180f159323cSdan  7 "+col REFERENCES tbl(x)"        col
1181f159323cSdan} {
1182f159323cSdan  do_execsql_test 1.$tn.1 "
1183f159323cSdan    CREATE VIRTUAL TABLE rt USING rtree_i32(k, a,b, $auxcol)
1184f159323cSdan  "
1185f159323cSdan
1186f159323cSdan  # Check that the aux column has no affinity. Or NOT NULL constraint.
1187f159323cSdan  # And that the aux column is the child key of an FK constraint.
1188f159323cSdan  #
1189f159323cSdan  do_execsql_test 1.$tn.2 "
1190f159323cSdan    INSERT INTO rt($nm) VALUES(NULL), (45), (-123.2), ('456'), (X'ABCD');
1191f159323cSdan    SELECT typeof($nm), quote($nm) FROM rt;
1192f159323cSdan  " {
1193f159323cSdan    null NULL
1194f159323cSdan    integer 45
1195f159323cSdan    real -123.2
1196f159323cSdan    text '456'
1197f159323cSdan    blob X'ABCD'
1198f159323cSdan  }
1199f159323cSdan
1200f159323cSdan  # Check that there is no UNIQUE constraint either.
1201f159323cSdan  #
1202f159323cSdan  do_execsql_test 1.$tn.3 "
1203f159323cSdan    INSERT INTO rt($nm) VALUES('xyz'), ('xyz'), ('xyz');
1204f159323cSdan  "
1205f159323cSdan
1206f159323cSdan  do_execsql_test 1.$tn.2 {
1207f159323cSdan    DROP TABLE rt
1208f159323cSdan  }
1209f159323cSdan}
1210f159323cSdan
1211f159323cSdan#-------------------------------------------------------------------------
1212f159323cSdan#-------------------------------------------------------------------------
1213f159323cSdan# Section 5 of documentation.
1214f159323cSdan#-------------------------------------------------------------------------
1215f159323cSdan#-------------------------------------------------------------------------
1216f159323cSdanset testprefix rtreedoc-10
1217f159323cSdan
1218f159323cSdan# EVIDENCE-OF: R-21011-43790 If integer coordinates are desired, declare
1219f159323cSdan# the table using "rtree_i32" instead: CREATE VIRTUAL TABLE intrtree
1220f159323cSdan# USING rtree_i32(id,x0,x1,y0,y1,z0,z1);
1221f159323cSdando_execsql_test 1.0 {
1222f159323cSdan  CREATE VIRTUAL TABLE intrtree USING rtree_i32(id,x0,x1,y0,y1,z0,z1);
1223f159323cSdan  INSERT INTO intrtree DEFAULT VALUES;
1224f159323cSdan  SELECT typeof(x0) FROM intrtree;
1225f159323cSdan} {integer}
1226f159323cSdan
1227f159323cSdan# EVIDENCE-OF: R-09193-49806 An rtree_i32 stores coordinates as 32-bit
1228f159323cSdan# signed integers.
1229f159323cSdan#
1230f159323cSdan# Show that coordinates are cast in a way consistent with casting to
1231f159323cSdan# a signed 32-bit integer.
1232f159323cSdando_execsql_test 1.1 {
1233f159323cSdan  DELETE FROM intrtree;
1234f159323cSdan  INSERT INTO intrtree VALUES(333,
1235f159323cSdan      1<<44, (1<<44)+1,
1236f159323cSdan      10000000000, 10000000001,
1237f159323cSdan      -10000000001, -10000000000
1238f159323cSdan  );
1239f159323cSdan  SELECT * FROM intrtree;
1240f159323cSdan} {
1241f159323cSdan  333 0 1 1410065408 1410065409 -1410065409 -1410065408
1242f159323cSdan}
1243f159323cSdan
1244f159323cSdan#-------------------------------------------------------------------------
1245f159323cSdan#-------------------------------------------------------------------------
1246f159323cSdan# Section 7.1 of documentation.
1247f159323cSdan#-------------------------------------------------------------------------
1248f159323cSdan#-------------------------------------------------------------------------
1249f159323cSdanset testprefix rtreedoc-11
1250f159323cSdanreset_db
1251f159323cSdan
1252f159323cSdan# This command assumes that the argument is a node blob for a 2 dimensional
1253f159323cSdan# i32 r-tree table. It decodes and returns a list of cells from the node
1254f159323cSdan# as a list. Each cell is itself a list of the following form:
1255f159323cSdan#
1256f159323cSdan#    {$rowid $minX $maxX $minY $maxY}
1257f159323cSdan#
1258f159323cSdan# For internal (non-leaf) nodes, the rowid is replaced by the child node
1259f159323cSdan# number.
1260f159323cSdan#
1261f159323cSdanproc rnode {aData} {
1262f159323cSdan  set nDim 2
1263f159323cSdan
1264f159323cSdan  set nData [string length $aData]
1265f159323cSdan  set nBytePerCell [expr (8 + 2*$nDim*4)]
1266f159323cSdan  binary scan [string range $aData 2 3] S nCell
1267f159323cSdan
1268f159323cSdan  set res [list]
1269f159323cSdan  for {set i 0} {$i < $nCell} {incr i} {
1270f159323cSdan    set iOff [expr $i*$nBytePerCell+4]
1271f159323cSdan    set cell [string range $aData $iOff [expr $iOff+$nBytePerCell-1]]
1272f159323cSdan    binary scan $cell WIIII rowid x1 x2 y1 y2
1273f159323cSdan    lappend res [list $rowid $x1 $x2 $y1 $y2]
1274f159323cSdan  }
1275f159323cSdan
1276f159323cSdan  return $res
1277f159323cSdan}
1278f159323cSdan
1279f159323cSdan# aData must be a node blob. This command returns true if the node contains
1280f159323cSdan# rowid $rowid, or false otherwise.
1281f159323cSdan#
1282f159323cSdanproc rnode_contains {aData rowid} {
1283f159323cSdan  set L [rnode $aData]
1284f159323cSdan  foreach cell $L {
1285f159323cSdan    set r [lindex $cell 0]
1286f159323cSdan    if {$r==$rowid} { return 1 }
1287f159323cSdan  }
1288f159323cSdan  return 0
1289f159323cSdan}
1290f159323cSdan
1291f02c324bSdanproc rnode_replace_cell {aData iCell cell} {
1292f02c324bSdan  set aCell [binary format WIIII {*}$cell]
1293f02c324bSdan  set nDim 2
1294f02c324bSdan  set nBytePerCell [expr (8 + 2*$nDim*4)]
1295f02c324bSdan  set iOff [expr $iCell*$nBytePerCell+4]
1296f02c324bSdan
1297f02c324bSdan  set aNew [binary format a*a*a* \
1298f02c324bSdan      [string range $aData 0 $iOff-1]     \
1299f02c324bSdan      $aCell     \
1300f02c324bSdan      [string range $aData $iOff+$nBytePerCell end] \
1301f02c324bSdan  ]
1302f02c324bSdan  return $aNew
1303f02c324bSdan}
1304f02c324bSdan
1305f159323cSdandb function rnode rnode
1306f159323cSdandb function rnode_contains rnode_contains
1307f02c324bSdandb function rnode_replace_cell rnode_replace_cell
1308f159323cSdan
1309f159323cSdanforeach {tn nm} {
1310f159323cSdan  1 x1
1311f159323cSdan  2 asdfghjkl
1312f159323cSdan  3 hello_world
1313f159323cSdan} {
1314f159323cSdan  do_execsql_test 1.$tn.1 "
1315f159323cSdan    CREATE VIRTUAL TABLE $nm USING rtree(a,b,c,d,e);
1316f159323cSdan  "
1317f159323cSdan
1318eda0001dSdan  # EVIDENCE-OF: R-33789-46762 The content of an R*Tree index is actually
1319eda0001dSdan  # stored in three ordinary SQLite tables with names derived from the
1320eda0001dSdan  # name of the R*Tree.
1321eda0001dSdan  #
1322eda0001dSdan  # EVIDENCE-OF: R-39849-06566 This is their schema: CREATE TABLE
1323eda0001dSdan  # %_node(nodeno INTEGER PRIMARY KEY, data) CREATE TABLE %_parent(nodeno
1324eda0001dSdan  # INTEGER PRIMARY KEY, parentnode) CREATE TABLE %_rowid(rowid INTEGER
1325eda0001dSdan  # PRIMARY KEY, nodeno)
1326f159323cSdan  #
1327f159323cSdan  # EVIDENCE-OF: R-07489-10051 The "%" in the name of each shadow table is
1328f159323cSdan  # replaced by the name of the R*Tree virtual table. So, if the name of
1329f159323cSdan  # the R*Tree table is "xyz" then the three shadow tables would be
1330f159323cSdan  # "xyz_node", "xyz_parent", and "xyz_rowid".
1331f159323cSdan  do_execsql_test 1.$tn.2 {
1332f159323cSdan    SELECT sql FROM sqlite_schema WHERE name!=$nm ORDER BY 1
1333f159323cSdan  } [string map [list % $nm] "
1334f159323cSdan    {CREATE TABLE \"%_node\"(nodeno INTEGER PRIMARY KEY,data)}
1335f159323cSdan    {CREATE TABLE \"%_parent\"(nodeno INTEGER PRIMARY KEY,parentnode)}
1336f159323cSdan    {CREATE TABLE \"%_rowid\"(rowid INTEGER PRIMARY KEY,nodeno)}
1337f159323cSdan  "]
1338f159323cSdan
1339f159323cSdan  do_execsql_test 1.$tn "DROP TABLE $nm"
1340f159323cSdan}
1341f159323cSdan
1342f159323cSdan
1343f159323cSdan# EVIDENCE-OF: R-51070-59303 There is one entry in the %_node table for
1344f159323cSdan# each R*Tree node.
1345f159323cSdan#
1346f159323cSdan# The following creates a 6 node r-tree structure.
1347f159323cSdan#
1348f159323cSdando_execsql_test 2.0 {
1349f159323cSdan  CREATE VIRTUAL TABLE r1 USING rtree_i32(i, x1,x2, y1,y2);
1350f159323cSdan  WITH t(i) AS (
1351f159323cSdan    VALUES(1) UNION SELECT i+1 FROM t WHERE i<110
1352f159323cSdan  )
1353f159323cSdan  INSERT INTO r1 SELECT i, (i%10), (i%10)+2, (i%6), (i%7)+6 FROM t;
1354f159323cSdan}
1355f159323cSdando_execsql_test 2.1 {
1356f159323cSdan  SELECT count(*) FROM r1_node;
1357f159323cSdan} 6
1358f159323cSdan
1359f159323cSdan# EVIDENCE-OF: R-27261-09153 All nodes other than the root have an entry
1360f159323cSdan# in the %_parent shadow table that identifies the parent node.
1361f159323cSdan#
1362f159323cSdan# In this case nodes 2-6 are the children of node 1.
1363f159323cSdan#
1364f159323cSdando_execsql_test 2.3 {
1365f159323cSdan  SELECT nodeno, parentnode FROM r1_parent
1366f159323cSdan} {2 1  3 1  4 1  5 1  6 1}
1367f159323cSdan
1368f159323cSdan# EVIDENCE-OF: R-02358-35037 The %_rowid shadow table maps entry rowids
1369f159323cSdan# to the node that contains that entry.
1370f159323cSdan#
1371f159323cSdando_execsql_test 2.4 {
1372f159323cSdan  SELECT 'failed' FROM r1_rowid WHERE 0==rnode_contains(
1373f159323cSdan    (SELECT data FROM r1_node WHERE nodeno=r1_rowid.nodeno), rowid
1374f159323cSdan  )
1375f159323cSdan}
1376f159323cSdando_test 2.5 {
1377f159323cSdan  db eval { SELECT nodeno, data FROM r1_node WHERE nodeno!=1 } {
1378f159323cSdan    set L [rnode $data]
1379f159323cSdan    foreach cell $L {
1380f159323cSdan      set rowid [lindex $cell 0]
1381f159323cSdan      set rowid_nodeno 0
1382f159323cSdan      db eval {SELECT nodeno AS rowid_nodeno FROM r1_rowid WHERE rowid=$rowid} {
1383f159323cSdan        break
1384f159323cSdan      }
1385f159323cSdan      if {$rowid_nodeno!=$nodeno} { error "data mismatch!" }
1386f159323cSdan    }
1387f159323cSdan  }
1388f159323cSdan} {}
1389f159323cSdan
1390f159323cSdan# EVIDENCE-OF: R-65201-22208 Extra columns appended to the %_rowid table
1391f159323cSdan# hold the content of auxiliary columns.
1392f159323cSdan#
1393f159323cSdan# EVIDENCE-OF: R-44161-28345 The names of these extra %_rowid columns
1394f159323cSdan# are probably not the same as the actual auxiliary column names.
1395f159323cSdan#
1396f159323cSdan# In this case, the auxiliary columns are named "e1" and "e2". The
1397f159323cSdan# extra %_rowid columns are named "a0" and "a1".
1398f159323cSdan#
1399f159323cSdando_execsql_test 3.0 {
1400f159323cSdan  CREATE VIRTUAL TABLE rtaux USING rtree(id, x1,x2, y1,y2, +e1, +e2);
1401f159323cSdan  SELECT sql FROM sqlite_schema WHERE name='rtaux_rowid';
1402f159323cSdan} {
1403f159323cSdan  {CREATE TABLE "rtaux_rowid"(rowid INTEGER PRIMARY KEY,nodeno,a0,a1)}
1404f159323cSdan}
1405f159323cSdando_execsql_test 3.1 {
1406f159323cSdan  INSERT INTO rtaux(e1, e2) VALUES('hello', 'world'), (123, 456);
1407f159323cSdan}
1408f159323cSdando_execsql_test 3.2 {
1409f159323cSdan  SELECT a0, a1 FROM rtaux_rowid;
1410f159323cSdan} {
1411f159323cSdan  hello world  123 456
1412f159323cSdan}
1413f159323cSdan
14145f835b78Sdan#-------------------------------------------------------------------------
14155f835b78Sdan#-------------------------------------------------------------------------
14165f835b78Sdan# Section 7.2 of documentation.
14175f835b78Sdan#-------------------------------------------------------------------------
14185f835b78Sdan#-------------------------------------------------------------------------
14195f835b78Sdanset testprefix rtreedoc-12
14205f835b78Sdanreset_db
14215f835b78Sdanforcedelete test.db2
14225f835b78Sdan
1423f02c324bSdandb function rnode rnode
1424f02c324bSdandb function rnode_contains rnode_contains
1425f02c324bSdandb function rnode_replace_cell rnode_replace_cell
1426f02c324bSdan
14275f835b78Sdan# EVIDENCE-OF: R-13571-45795 The scalar SQL function rtreecheck(R) or
14285f835b78Sdan# rtreecheck(S,R) runs an integrity check on the rtree table named R
14295f835b78Sdan# contained within database S.
14305f835b78Sdan#
14315f835b78Sdan# EVIDENCE-OF: R-36011-59963 The function returns a human-language
14325f835b78Sdan# description of any problems found, or the string 'ok' if everything is
14335f835b78Sdan# ok.
14345f835b78Sdan#
14355f835b78Sdando_execsql_test 1.0 {
14365f835b78Sdan  CREATE VIRTUAL TABLE rt1 USING rtree(id, a, b);
14375f835b78Sdan  WITH s(i) AS (
14385f835b78Sdan    VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<200
14395f835b78Sdan  )
14405f835b78Sdan  INSERT INTO rt1 SELECT i, i, i FROM s;
14415f835b78Sdan
14425f835b78Sdan  ATTACH 'test.db2' AS 'aux';
14435f835b78Sdan  CREATE VIRTUAL TABLE aux.rt1 USING rtree(id, a, b);
14445f835b78Sdan  INSERT INTO aux.rt1 SELECT * FROM rt1;
14455f835b78Sdan}
14465f835b78Sdan
14475f835b78Sdando_execsql_test 1.1.1 { SELECT rtreecheck('rt1'); } {ok}
14485f835b78Sdando_execsql_test 1.1.2 { SELECT rtreecheck('main', 'rt1'); } {ok}
14495f835b78Sdando_execsql_test 1.1.3 { SELECT rtreecheck('aux', 'rt1'); } {ok}
14505f835b78Sdando_catchsql_test 1.1.4 {
14515f835b78Sdan  SELECT rtreecheck('nosuchdb', 'rt1');
14525f835b78Sdan} {1 {SQL logic error}}
14535f835b78Sdan
14545f835b78Sdan# Corrupt the table in database 'main':
14555f835b78Sdando_execsql_test 1.2.1 { UPDATE rt1_node SET nodeno=21 WHERE nodeno=3; }
14565f835b78Sdando_execsql_test 1.2.1 { SELECT rtreecheck('rt1')=='ok'; } {0}
14575f835b78Sdando_execsql_test 1.2.2 { SELECT rtreecheck('main', 'rt1')=='ok'; } {0}
14585f835b78Sdando_execsql_test 1.2.3 { SELECT rtreecheck('aux', 'rt1')=='ok'; } {1}
14595f835b78Sdando_execsql_test 1.2.4 { UPDATE rt1_node SET nodeno=3 WHERE nodeno=21; }
14605f835b78Sdan
14615f835b78Sdan# Corrupt the table in database 'aux':
14625f835b78Sdando_execsql_test 1.2.1 { UPDATE aux.rt1_node SET nodeno=21 WHERE nodeno=3; }
14635f835b78Sdando_execsql_test 1.2.1 { SELECT rtreecheck('rt1')=='ok'; } {1}
14645f835b78Sdando_execsql_test 1.2.2 { SELECT rtreecheck('main', 'rt1')=='ok'; } {1}
14655f835b78Sdando_execsql_test 1.2.3 { SELECT rtreecheck('aux', 'rt1')=='ok'; } {0}
14665f835b78Sdando_execsql_test 1.2.4 { UPDATE rt1_node SET nodeno=3 WHERE nodeno=21; }
14675f835b78Sdan
14685f835b78Sdan# EVIDENCE-OF: R-45759-33459 Example: To verify that an R*Tree named
14695f835b78Sdan# "demo_index" is well-formed and internally consistent, run: SELECT
14705f835b78Sdan# rtreecheck('demo_index');
14715f835b78Sdando_execsql_test 2.0 {
14725f835b78Sdan  CREATE VIRTUAL TABLE demo_index USING rtree(id, x1,x2, y1,y2);
14735f835b78Sdan  INSERT INTO demo_index SELECT id, a, b, a, b FROM rt1;
14745f835b78Sdan}
14755f835b78Sdando_execsql_test 2.1 { SELECT rtreecheck('demo_index') } {ok}
14765f835b78Sdando_execsql_test 2.2 {
14775f835b78Sdan  UPDATE demo_index_rowid SET nodeno=44 WHERE rowid=44;
14785f835b78Sdan  SELECT rtreecheck('demo_index');
14795f835b78Sdan} {{Found (44 -> 44) in %_rowid table, expected (44 -> 4)}}
1480a2fef2f0Sdan
1481f02c324bSdan
1482f02c324bSdando_execsql_test 3.0 {
1483f02c324bSdan  CREATE VIRTUAL TABLE rt2 USING rtree_i32(id, a, b, c, d);
1484f02c324bSdan  WITH s(i) AS (
1485f02c324bSdan    VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<200
1486f02c324bSdan  )
1487f02c324bSdan  INSERT INTO rt2 SELECT i, i, i+2, i, i+2 FROM s;
1488f02c324bSdan}
1489f02c324bSdan
1490f02c324bSdan# EVIDENCE-OF: R-02555-31045 for each dimension, (coord1 <= coord2).
1491f02c324bSdan#
1492f02c324bSdanexecsql BEGIN
1493f02c324bSdando_test 3.1 {
1494f02c324bSdan  set cell [
1495f02c324bSdan    lindex [execsql {SELECT rnode(data) FROM rt2_node WHERE nodeno=3}] 0 3
1496f02c324bSdan  ]
1497f02c324bSdan  set cell [list [lindex $cell 0]       \
1498f02c324bSdan    [lindex $cell 2] [lindex $cell 1]   \
1499f02c324bSdan    [lindex $cell 3] [lindex $cell 4]   \
1500f02c324bSdan  ]
1501f02c324bSdan  execsql {
1502f02c324bSdan    UPDATE rt2_node SET data=rnode_replace_cell(data, 3, $cell) WHERE nodeno=3
1503f02c324bSdan  }
1504f02c324bSdan  execsql { SELECT rtreecheck('rt2') }
1505f02c324bSdan} {{Dimension 0 of cell 3 on node 3 is corrupt}}
1506f02c324bSdanexecsql ROLLBACK
1507f02c324bSdan
1508f02c324bSdan# EVIDENCE-OF: R-13844-15873 unless the cell is on the root node, that
1509f02c324bSdan# the cell is bounded by the parent cell on the parent node.
1510f02c324bSdan#
1511f02c324bSdanexecsql BEGIN
1512f02c324bSdando_test 3.2 {
1513f02c324bSdan  set cell [
1514f02c324bSdan    lindex [execsql {SELECT rnode(data) FROM rt2_node WHERE nodeno=3}] 0 3
1515f02c324bSdan  ]
1516f02c324bSdan  lset cell 3 450
1517f02c324bSdan  lset cell 4 451
1518f02c324bSdan  execsql {
1519f02c324bSdan    UPDATE rt2_node SET data=rnode_replace_cell(data, 3, $cell) WHERE nodeno=3
1520f02c324bSdan  }
1521f02c324bSdan  execsql { SELECT rtreecheck('rt2') }
1522f02c324bSdan} {{Dimension 1 of cell 3 on node 3 is corrupt relative to parent}}
1523f02c324bSdanexecsql ROLLBACK
1524f02c324bSdan
1525f02c324bSdan# EVIDENCE-OF: R-02505-03621 for leaf nodes, that there is an entry in
1526f02c324bSdan# the %_rowid table corresponding to the cell's rowid value that points
1527f02c324bSdan# to the correct node.
1528f02c324bSdan#
1529f02c324bSdanexecsql BEGIN
1530f02c324bSdando_test 3.3 {
1531f02c324bSdan  execsql {
1532f02c324bSdan    UPDATE rt2_rowid SET rowid=452 WHERE rowid=100
1533f02c324bSdan  }
1534f02c324bSdan  execsql { SELECT rtreecheck('rt2') }
1535f02c324bSdan} {{Mapping (100 -> 6) missing from %_rowid table}}
1536f02c324bSdanexecsql ROLLBACK
1537f02c324bSdan
1538f02c324bSdan# EVIDENCE-OF: R-50927-02218 for cells on non-leaf nodes, that there is
1539f02c324bSdan# an entry in the %_parent table mapping from the cell's child node to
1540f02c324bSdan# the node that it resides on.
1541f02c324bSdan#
1542f02c324bSdanexecsql BEGIN
1543f02c324bSdando_test 3.4.1 {
1544f02c324bSdan  execsql {
1545f02c324bSdan    UPDATE rt2_parent SET parentnode=123 WHERE nodeno=3
1546f02c324bSdan  }
1547f02c324bSdan  execsql { SELECT rtreecheck('rt2') }
1548f02c324bSdan} {{Found (3 -> 123) in %_parent table, expected (3 -> 1)}}
1549f02c324bSdanexecsql ROLLBACK
1550f02c324bSdanexecsql BEGIN
1551f02c324bSdando_test 3.4.2 {
1552f02c324bSdan  execsql {
1553f02c324bSdan    UPDATE rt2_parent SET nodeno=123 WHERE nodeno=3
1554f02c324bSdan  }
1555f02c324bSdan  execsql { SELECT rtreecheck('rt2') }
1556f02c324bSdan} {{Mapping (3 -> 1) missing from %_parent table}}
1557f02c324bSdanexecsql ROLLBACK
1558f02c324bSdan
1559f02c324bSdan# EVIDENCE-OF: R-23235-09153 That there are the same number of entries
1560f02c324bSdan# in the %_rowid table as there are leaf cells in the r-tree structure,
1561f02c324bSdan# and that there is a leaf cell that corresponds to each entry in the
1562f02c324bSdan# %_rowid table.
1563f02c324bSdanexecsql BEGIN
1564f02c324bSdando_test 3.5 {
1565f02c324bSdan  execsql { INSERT INTO rt2_rowid VALUES(1000, 1000) }
1566f02c324bSdan  execsql { SELECT rtreecheck('rt2') }
1567f02c324bSdan} {{Wrong number of entries in %_rowid table - expected 200, actual 201}}
1568f02c324bSdanexecsql ROLLBACK
1569f02c324bSdan
1570f02c324bSdan# EVIDENCE-OF: R-62800-43436 That there are the same number of entries
1571f02c324bSdan# in the %_parent table as there are non-leaf cells in the r-tree
1572f02c324bSdan# structure, and that there is a non-leaf cell that corresponds to each
1573f02c324bSdan# entry in the %_parent table.
1574f02c324bSdanexecsql BEGIN
1575f02c324bSdando_test 3.6 {
1576f02c324bSdan  execsql { INSERT INTO rt2_parent VALUES(1000, 1000) }
1577f02c324bSdan  execsql { SELECT rtreecheck('rt2') }
1578f02c324bSdan} {{Wrong number of entries in %_parent table - expected 9, actual 10}}
1579f02c324bSdanexecsql ROLLBACK
1580f02c324bSdan
1581f02c324bSdan
1582f02c324bSdan
1583a2fef2f0Sdanfinish_test
1584