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