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