rtreedoc.test 53 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594
  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. if {![info exists testdir]} {
  15. set testdir [file join [file dirname [info script]] .. .. test]
  16. }
  17. source [file join [file dirname [info script]] rtree_util.tcl]
  18. source $testdir/tester.tcl
  19. set testprefix rtreedoc
  20. ifcapable !rtree {
  21. finish_test
  22. return
  23. }
  24. # This command returns the number of columns in table $tbl within the
  25. # database opened by database handle $db
  26. proc column_count {db tbl} {
  27. set nCol 0
  28. $db eval "PRAGMA table_info = $tbl" { incr nCol }
  29. return $nCol
  30. }
  31. proc column_name_list {db tbl} {
  32. set lCol [list]
  33. $db eval "PRAGMA table_info = $tbl" {
  34. lappend lCol $name
  35. }
  36. return $lCol
  37. }
  38. unset -nocomplain res
  39. #-------------------------------------------------------------------------
  40. #-------------------------------------------------------------------------
  41. # Section 3 of documentation.
  42. #-------------------------------------------------------------------------
  43. #-------------------------------------------------------------------------
  44. set testprefix rtreedoc-1
  45. # EVIDENCE-OF: R-15060-13876 A 1-dimensional R*Tree thus has 3 columns.
  46. do_execsql_test 1.1.1 { CREATE VIRTUAL TABLE rt1 USING rtree(id, x1,x2) }
  47. do_test 1.1.2 { column_count db rt1 } 3
  48. # EVIDENCE-OF: R-19353-19546 A 2-dimensional R*Tree has 5 columns.
  49. do_execsql_test 1.2.1 { CREATE VIRTUAL TABLE rt2 USING rtree(id,x1,x2, y1,y2) }
  50. do_test 1.2.2 { column_count db rt2 } 5
  51. # EVIDENCE-OF: R-13615-19528 A 3-dimensional R*Tree has 7 columns.
  52. do_execsql_test 1.3.1 {
  53. CREATE VIRTUAL TABLE rt3 USING rtree(id, x1,x2, y1,y2, z1,z2)
  54. }
  55. do_test 1.3.2 { column_count db rt3 } 7
  56. # EVIDENCE-OF: R-53479-41922 A 4-dimensional R*Tree has 9 columns.
  57. do_execsql_test 1.4.1 {
  58. CREATE VIRTUAL TABLE rt4 USING rtree(id, x1,x2, y1,y2, z1,z2, v1,v2)
  59. }
  60. do_test 1.4.2 { column_count db rt4 } 9
  61. # EVIDENCE-OF: R-13981-28768 And a 5-dimensional R*Tree has 11 columns.
  62. do_execsql_test 1.5.1 {
  63. CREATE VIRTUAL TABLE rt5 USING rtree(id, x1,x2, y1,y2, z1,z2, v1,v2, w1,w2)
  64. }
  65. do_test 1.5.2 { column_count db rt5 } 11
  66. # Attempt to create r-tree tables with 6 and 7 dimensions.
  67. #
  68. # EVIDENCE-OF: R-61533-25862 The SQLite R*Tree implementation does not
  69. # support R*Trees wider than 5 dimensions.
  70. do_catchsql_test 2.1.1 {
  71. CREATE VIRTUAL TABLE rt6 USING rtree(
  72. id, x1,x2, y1,y2, z1,z2, v1,v2, w1,w2, a1,a2
  73. )
  74. } {1 {Too many columns for an rtree table}}
  75. do_catchsql_test 2.1.2 {
  76. CREATE VIRTUAL TABLE rt6 USING rtree(
  77. id, x1,x2, y1,y2, z1,z2, v1,v2, w1,w2, a1,a2, b1, b2
  78. )
  79. } {1 {Too many columns for an rtree table}}
  80. # Attempt to create r-tree tables with no columns, a single column, or
  81. # an even number of columns. This and the tests above establish that:
  82. #
  83. # EVIDENCE-OF: R-16717-50504 Each R*Tree index is a virtual table with
  84. # an odd number of columns between 3 and 11.
  85. foreach {tn cols err} {
  86. 1 "" "Too few columns for an rtree table"
  87. 2 "x" "Too few columns for an rtree table"
  88. 3 "x,y" "Too few columns for an rtree table"
  89. 4 "a,b,c,d" "Wrong number of columns for an rtree table"
  90. 5 "a,b,c,d,e,f" "Wrong number of columns for an rtree table"
  91. 6 "a,b,c,d,e,f,g,h" "Wrong number of columns for an rtree table"
  92. 7 "a,b,c,d,e,f,g,h,i,j" "Wrong number of columns for an rtree table"
  93. 8 "a,b,c,d,e,f,g,h,i,j,k,l" "Too many columns for an rtree table"
  94. } {
  95. do_catchsql_test 3.$tn "
  96. CREATE VIRTUAL TABLE xyz USING rtree($cols)
  97. " [list 1 $err]
  98. }
  99. # EVIDENCE-OF: R-17874-21123 The first column of an SQLite R*Tree is
  100. # similar to an integer primary key column of a normal SQLite table.
  101. #
  102. # EVIDENCE-OF: R-46619-65417 The first column is always a 64-bit signed
  103. # integer primary key.
  104. #
  105. # EVIDENCE-OF: R-46866-24036 It may only store a 64-bit signed integer
  106. # value.
  107. #
  108. # EVIDENCE-OF: R-00250-64843 If an attempt is made to insert any other
  109. # non-integer value into this column, the r-tree module silently
  110. # converts it to an integer before writing it into the database.
  111. #
  112. do_execsql_test 4.0 { CREATE VIRTUAL TABLE rt USING rtree(id, x1, x2) }
  113. foreach {tn val res} {
  114. 1 10 10
  115. 2 10.6 10
  116. 3 10.99 10
  117. 4 '123' 123
  118. 5 X'313233' 123
  119. 6 -10 -10
  120. 7 9223372036854775807 9223372036854775807
  121. 8 -9223372036854775808 -9223372036854775808
  122. 9 '9223372036854775807' 9223372036854775807
  123. 10 '-9223372036854775808' -9223372036854775808
  124. 11 'hello+world' 0
  125. } {
  126. do_execsql_test 4.$tn.1 "
  127. DELETE FROM rt;
  128. INSERT INTO rt VALUES($val, 10, 20);
  129. "
  130. do_execsql_test 4.$tn.2 {
  131. SELECT typeof(id), id FROM rt
  132. } [list integer $res]
  133. }
  134. # EVIDENCE-OF: R-15544-29079 Inserting a NULL value into this column
  135. # causes SQLite to automatically generate a new unique primary key
  136. # value.
  137. do_execsql_test 5.1 {
  138. DELETE FROM rt;
  139. INSERT INTO rt VALUES(100, 1, 2);
  140. INSERT INTO rt VALUES(NULL, 1, 2);
  141. }
  142. do_execsql_test 5.2 { SELECT id FROM rt } {100 101}
  143. do_execsql_test 5.3 {
  144. INSERT INTO rt VALUES(9223372036854775807, 1, 2);
  145. INSERT INTO rt VALUES(NULL, 1, 2);
  146. }
  147. do_execsql_test 5.4 {
  148. SELECT count(*) FROM rt;
  149. } 4
  150. do_execsql_test 5.5 {
  151. SELECT id IN(100, 101, 9223372036854775807) FROM rt ORDER BY 1;
  152. } {0 1 1 1}
  153. # EVIDENCE-OF: R-64317-38978 The other columns are pairs, one pair per
  154. # dimension, containing the minimum and maximum values for that
  155. # dimension, respectively.
  156. #
  157. # Show this by observing that attempts to insert rows with max>min fail.
  158. #
  159. do_execsql_test 6.1 {
  160. CREATE VIRTUAL TABLE rtF USING rtree(id, x1,x2, y1,y2);
  161. CREATE VIRTUAL TABLE rtI USING rtree_i32(id, x1,x2, y1,y2, z1,z2);
  162. }
  163. foreach {tn x1 x2 y1 y2 ok} {
  164. 1 10.3 20.1 30.9 40.2 1
  165. 2 10.3 20.1 40.2 30.9 0
  166. 3 10.3 30.9 20.1 40.2 1
  167. 4 20.1 10.3 30.9 40.2 0
  168. } {
  169. do_test 6.2.$tn {
  170. catch { db eval { INSERT INTO rtF VALUES(NULL, $x1, $x2, $y1, $y2) } }
  171. } [expr $ok==0]
  172. }
  173. foreach {tn x1 x2 y1 y2 z1 z2 ok} {
  174. 1 10 20 30 40 50 60 1
  175. 2 10 20 30 40 60 50 0
  176. 3 10 20 30 50 40 60 1
  177. 4 10 20 40 30 50 60 0
  178. 5 10 30 20 40 50 60 1
  179. 6 20 10 30 40 50 60 0
  180. } {
  181. do_test 6.3.$tn {
  182. catch { db eval { INSERT INTO rtI VALUES(NULL,$x1,$x2,$y1,$y2,$z1,$z2) } }
  183. } [expr $ok==0]
  184. }
  185. # EVIDENCE-OF: R-08054-15429 The min/max-value pair columns are stored
  186. # as 32-bit floating point values for "rtree" virtual tables or as
  187. # 32-bit signed integers in "rtree_i32" virtual tables.
  188. #
  189. # Show this by showing that large values are rounded in ways consistent
  190. # with those two 32-bit types.
  191. do_execsql_test 7.1 {
  192. DELETE FROM rtI;
  193. INSERT INTO rtI VALUES(
  194. 0, -2000000000, 2000000000, -5000000000, 5000000000,
  195. -1000000000000, 10000000000000
  196. );
  197. SELECT * FROM rtI;
  198. } {
  199. 0 -2000000000 2000000000 -705032704 705032704 727379968 1316134912
  200. }
  201. do_execsql_test 7.2 {
  202. DELETE FROM rtF;
  203. INSERT INTO rtF VALUES(
  204. 0, -2000000000, 2000000000,
  205. -1000000000000, 10000000000000
  206. );
  207. SELECT * FROM rtF;
  208. } {
  209. 0 -2000000000.0 2000000000.0 -1000000126976.0 10000000876544.0
  210. }
  211. # EVIDENCE-OF: R-47371-54529 Unlike regular SQLite tables which can
  212. # store data in a variety of datatypes and formats, the R*Tree rigidly
  213. # enforce these storage types.
  214. #
  215. # EVIDENCE-OF: R-39153-14977 If any other type of value is inserted into
  216. # such a column, the r-tree module silently converts it to the required
  217. # type before writing the new record to the database.
  218. do_execsql_test 8.1 {
  219. DELETE FROM rtI;
  220. INSERT INTO rtI VALUES(
  221. 1, 'hello world', X'616263', NULL, 44.5, 1000, 9999.9999
  222. );
  223. SELECT * FROM rtI;
  224. } {
  225. 1 0 0 0 44 1000 9999
  226. }
  227. do_execsql_test 8.2 {
  228. SELECT
  229. typeof(x1), typeof(x2), typeof(y1), typeof(y2), typeof(z1), typeof(z2)
  230. FROM rtI
  231. } {integer integer integer integer integer integer}
  232. do_execsql_test 8.3 {
  233. DELETE FROM rtF;
  234. INSERT INTO rtF VALUES(
  235. 1, 'hello world', X'616263', NULL, 44
  236. );
  237. SELECT * FROM rtF;
  238. } {
  239. 1 0.0 0.0 0.0 44.0
  240. }
  241. do_execsql_test 8.4 {
  242. SELECT
  243. typeof(x1), typeof(x2), typeof(y1), typeof(y2)
  244. FROM rtF
  245. } {real real real real}
  246. #-------------------------------------------------------------------------
  247. #-------------------------------------------------------------------------
  248. # Section 3.1 of documentation.
  249. #-------------------------------------------------------------------------
  250. #-------------------------------------------------------------------------
  251. set testprefix rtreedoc-2
  252. reset_db
  253. foreach {tn name clist} {
  254. 1 t1 "id x1 x2"
  255. 2 t2 "id x1 x2 y1 y2 z1 z2"
  256. } {
  257. # EVIDENCE-OF: R-15142-18077 A new R*Tree index is created as follows:
  258. # CREATE VIRTUAL TABLE <name> USING rtree(<column-names>);
  259. do_execsql_test 1.$tn.1 "
  260. CREATE VIRTUAL TABLE $name USING rtree([join $clist ,])
  261. "
  262. # EVIDENCE-OF: R-51698-09302 The <name> is the name your
  263. # application chooses for the R*Tree index and <column-names> is a
  264. # comma separated list of between 3 and 11 columns.
  265. do_test 1.$tn.2 { column_name_list db $name } [list {*}$clist]
  266. # EVIDENCE-OF: R-50130-53472 The virtual <name> table creates
  267. # three shadow tables to actually store its content.
  268. do_execsql_test 1.$tn.3 {
  269. SELECT count(*) FROM sqlite_schema
  270. } [expr 1+3]
  271. # EVIDENCE-OF: R-45256-35998 The names of these shadow tables are:
  272. # <name>_node <name>_rowid <name>_parent
  273. do_execsql_test 1.$tn.4 {
  274. SELECT name FROM sqlite_schema WHERE rootpage>0 ORDER BY 1
  275. } [list ${name}_node ${name}_parent ${name}_rowid]
  276. do_execsql_test 1.$tn.5 "DROP TABLE $name"
  277. }
  278. # EVIDENCE-OF: R-11241-54478 As an example, consider creating a
  279. # two-dimensional R*Tree index for use in spatial queries: CREATE
  280. # VIRTUAL TABLE demo_index USING rtree( id, -- Integer primary key minX,
  281. # maxX, -- Minimum and maximum X coordinate minY, maxY -- Minimum and
  282. # maximum Y coordinate );
  283. do_execsql_test 2.0 {
  284. CREATE VIRTUAL TABLE demo_index USING rtree(
  285. id, -- Integer primary key
  286. minX, maxX, -- Minimum and maximum X coordinate
  287. minY, maxY -- Minimum and maximum Y coordinate
  288. );
  289. INSERT INTO demo_index VALUES(1,2,3,4,5);
  290. INSERT INTO demo_index VALUES(6,7,8,9,10);
  291. }
  292. # EVIDENCE-OF: R-02287-33529 The shadow tables are ordinary SQLite data
  293. # tables.
  294. #
  295. # Ordinary tables. With ordinary sqlite_schema entries.
  296. do_execsql_test 2.1 {
  297. SELECT type, name, sql FROM sqlite_schema WHERE sql NOT LIKE '%virtual%'
  298. } {
  299. table demo_index_rowid
  300. {CREATE TABLE "demo_index_rowid"(rowid INTEGER PRIMARY KEY,nodeno)}
  301. table demo_index_node
  302. {CREATE TABLE "demo_index_node"(nodeno INTEGER PRIMARY KEY,data)}
  303. table demo_index_parent
  304. {CREATE TABLE "demo_index_parent"(nodeno INTEGER PRIMARY KEY,parentnode)}
  305. }
  306. # EVIDENCE-OF: R-10863-13089 You can query them directly if you like,
  307. # though this unlikely to reveal anything particularly useful.
  308. #
  309. # Querying:
  310. do_execsql_test 2.2 {
  311. SELECT count(*) FROM demo_index_node;
  312. SELECT count(*) FROM demo_index_rowid;
  313. SELECT count(*) FROM demo_index_parent;
  314. } {1 2 0}
  315. # EVIDENCE-OF: R-05650-46070 And you can UPDATE, DELETE, INSERT or even
  316. # DROP the shadow tables, though doing so will corrupt your R*Tree
  317. # index.
  318. do_execsql_test 2.3 {
  319. DELETE FROM demo_index_rowid;
  320. INSERT INTO demo_index_parent VALUES(2, 3);
  321. UPDATE demo_index_node SET data = 'hello world'
  322. }
  323. do_catchsql_test 2.4 {
  324. SELECT * FROM demo_index WHERE minX>10 AND maxX<30
  325. } {1 {database disk image is malformed}}
  326. do_execsql_test 2.5 {
  327. DROP TABLE demo_index_rowid
  328. }
  329. #-------------------------------------------------------------------------
  330. #-------------------------------------------------------------------------
  331. # Section 3.1.1 of documentation.
  332. #-------------------------------------------------------------------------
  333. #-------------------------------------------------------------------------
  334. set testprefix rtreedoc-3
  335. reset_db
  336. # EVIDENCE-OF: R-44253-50720 In the argments to "rtree" in the CREATE
  337. # VIRTUAL TABLE statement, the names of the columns are taken from the
  338. # first token of each argument. All subsequent tokens within each
  339. # argument are silently ignored.
  340. #
  341. foreach {tn cols lCol} {
  342. 1 {(id TEXT, x1 TEXT, x2 TEXT, y1 TEXT, y2 TEXT)} {id x1 x2 y1 y2}
  343. 2 {(id TEXT, x1 UNIQUE, x2 TEXT, y1 NOT NULL, y2 TEXT)} {id x1 x2 y1 y2}
  344. 3 {(id, x1 DEFAULT 4, x2 TEXT, y1 NOT NULL, y2 TEXT)} {id x1 x2 y1 y2}
  345. } {
  346. do_execsql_test 1.$tn.1 " CREATE VIRTUAL TABLE abc USING rtree $cols "
  347. do_test 1.$tn.2 { column_name_list db abc } $lCol
  348. # EVIDENCE-OF: R-52032-06717 This means, for example, that if you try to
  349. # give a column a type affinity or add a constraint such as UNIQUE or
  350. # NOT NULL or DEFAULT to a column, those extra tokens are accepted as
  351. # valid, but they do not change the behavior of the rtree.
  352. # Show there are no UNIQUE constraints
  353. do_execsql_test 1.$tn.3 {
  354. INSERT INTO abc VALUES(1, 10.0, 20.0, 10.0, 20.0);
  355. INSERT INTO abc VALUES(2, 10.0, 20.0, 10.0, 20.0);
  356. }
  357. # Show the default values have not been modified
  358. do_execsql_test 1.$tn.4 {
  359. INSERT INTO abc DEFAULT VALUES;
  360. SELECT * FROM abc WHERE rowid NOT IN (1,2)
  361. } {3 0.0 0.0 0.0 0.0}
  362. # Show that there are no NOT NULL constraints
  363. do_execsql_test 1.$tn.5 {
  364. INSERT INTO abc VALUES(NULL, NULL, NULL, NULL, NULL);
  365. SELECT * FROM abc WHERE rowid NOT IN (1,2,3)
  366. } {4 0.0 0.0 0.0 0.0}
  367. # EVIDENCE-OF: R-06893-30579 In an RTREE virtual table, the first column
  368. # always has a type affinity of INTEGER and all other data columns have
  369. # a type affinity of REAL.
  370. do_execsql_test 1.$tn.5 {
  371. INSERT INTO abc VALUES('5', '5', '5', '5', '5');
  372. SELECT * FROM abc WHERE rowid NOT IN (1,2,3,4)
  373. } {5 5.0 5.0 5.0 5.0}
  374. do_execsql_test 1.$tn.6 {
  375. SELECT type FROM pragma_table_info('abc') ORDER BY cid
  376. } {INT REAL REAL REAL REAL}
  377. do_execsql_test 1.$tn.7 " CREATE VIRTUAL TABLE abc2 USING rtree_i32 $cols "
  378. # EVIDENCE-OF: R-06224-52418 In an RTREE_I32 virtual table, all columns
  379. # have type affinity of INTEGER.
  380. do_execsql_test 1.$tn.8 {
  381. INSERT INTO abc2 VALUES('6.0', '6.0', '6.0', '6.0', '6.0');
  382. SELECT * FROM abc2
  383. } {6 6 6 6 6}
  384. do_execsql_test 1.$tn.9 {
  385. SELECT type FROM pragma_table_info('abc2') ORDER BY cid
  386. } {INT INT INT INT INT}
  387. do_execsql_test 1.$tn.10 {
  388. DROP TABLE abc;
  389. DROP TABLE abc2;
  390. }
  391. }
  392. #-------------------------------------------------------------------------
  393. #-------------------------------------------------------------------------
  394. # Section 3.2 of documentation.
  395. #-------------------------------------------------------------------------
  396. #-------------------------------------------------------------------------
  397. set testprefix rtreedoc-4
  398. reset_db
  399. # EVIDENCE-OF: R-36195-31555 The usual INSERT, UPDATE, and DELETE
  400. # commands work on an R*Tree index just like on regular tables.
  401. #
  402. # Create a regular table and an rtree table. Perform INSERT, UPDATE and
  403. # DELETE operations, then observe that the contents of the two tables
  404. # are identical.
  405. do_execsql_test 1.0 {
  406. CREATE VIRTUAL TABLE rt USING rtree(id, x1, x2);
  407. CREATE TABLE t1(id INTEGER PRIMARY KEY, x1 REAL, x2 REAL);
  408. }
  409. foreach {tn sql} {
  410. 1 "INSERT INTO %TBL% VALUES(5, 11,12)"
  411. 2 "INSERT INTO %TBL% VALUES(11, -11,14.5)"
  412. 3 "UPDATE %TBL% SET x1=-99 WHERE id=11"
  413. 4 "DELETE FROM %TBL% WHERE x2=14.5"
  414. 5 "DELETE FROM %TBL%"
  415. } {
  416. set sql1 [string map {%TBL% rt} $sql]
  417. set sql2 [string map {%TBL% t1} $sql]
  418. do_execsql_test 1.$tn.0 $sql1
  419. do_execsql_test 1.$tn.1 $sql2
  420. set data1 [execsql {SELECT * FROM rt ORDER BY 1}]
  421. set data2 [execsql {SELECT * FROM t1 ORDER BY 1}]
  422. set res [expr {$data1==$data2}]
  423. do_test 1.$tn.2 {set res} 1
  424. }
  425. # EVIDENCE-OF: R-56987-45305
  426. do_execsql_test 2.0 {
  427. CREATE VIRTUAL TABLE demo_index USING rtree(
  428. id, -- Integer primary key
  429. minX, maxX, -- Minimum and maximum X coordinate
  430. minY, maxY -- Minimum and maximum Y coordinate
  431. );
  432. INSERT INTO demo_index VALUES
  433. (28215, -80.781227, -80.604706, 35.208813, 35.297367),
  434. (28216, -80.957283, -80.840599, 35.235920, 35.367825),
  435. (28217, -80.960869, -80.869431, 35.133682, 35.208233),
  436. (28226, -80.878983, -80.778275, 35.060287, 35.154446),
  437. (28227, -80.745544, -80.555382, 35.130215, 35.236916),
  438. (28244, -80.844208, -80.841988, 35.223728, 35.225471),
  439. (28262, -80.809074, -80.682938, 35.276207, 35.377747),
  440. (28269, -80.851471, -80.735718, 35.272560, 35.407925),
  441. (28270, -80.794983, -80.728966, 35.059872, 35.161823),
  442. (28273, -80.994766, -80.875259, 35.074734, 35.172836),
  443. (28277, -80.876793, -80.767586, 35.001709, 35.101063),
  444. (28278, -81.058029, -80.956375, 35.044701, 35.223812),
  445. (28280, -80.844208, -80.841972, 35.225468, 35.227203),
  446. (28282, -80.846382, -80.844193, 35.223972, 35.225655);
  447. }
  448. #-------------------------------------------------------------------------
  449. #-------------------------------------------------------------------------
  450. # Section 3.3 of documentation.
  451. #-------------------------------------------------------------------------
  452. #-------------------------------------------------------------------------
  453. set testprefix rtreedoc-5
  454. do_execsql_test 1.0 {
  455. INSERT INTO demo_index
  456. SELECT NULL, minX, maxX, minY+0.2, maxY+0.2 FROM demo_index;
  457. INSERT INTO demo_index
  458. SELECT NULL, minX+0.2, maxX+0.2, minY, maxY FROM demo_index;
  459. INSERT INTO demo_index
  460. SELECT NULL, minX, maxX, minY+0.4, maxY+0.4 FROM demo_index;
  461. INSERT INTO demo_index
  462. SELECT NULL, minX+0.4, maxX+0.4, minY, maxY FROM demo_index;
  463. INSERT INTO demo_index
  464. SELECT NULL, minX, maxX, minY+0.8, maxY+0.8 FROM demo_index;
  465. INSERT INTO demo_index
  466. SELECT NULL, minX+0.8, maxX+0.8, minY, maxY FROM demo_index;
  467. SELECT count(*) FROM demo_index;
  468. } {896}
  469. proc do_vmstep_test {tn sql expr} {
  470. execsql $sql
  471. set step [db status vmstep]
  472. do_test $tn.$step "expr {[subst $expr]}" 1
  473. }
  474. # EVIDENCE-OF: R-45880-07724 Any valid query will work against an R*Tree
  475. # index.
  476. do_execsql_test 1.1.0 {
  477. CREATE TABLE demo_tbl AS SELECT * FROM demo_index;
  478. }
  479. foreach {tn sql} {
  480. 1 {SELECT * FROM %TBL% ORDER BY 1}
  481. 2 {SELECT max(minX) FROM %TBL% ORDER BY 1}
  482. 3 {SELECT max(minX) FROM %TBL% GROUP BY round(minY) ORDER BY 1}
  483. } {
  484. set sql1 [string map {%TBL% demo_index} $sql]
  485. set sql2 [string map {%TBL% demo_tbl} $sql]
  486. do_execsql_test 1.1.$tn $sql1 [execsql $sql2]
  487. }
  488. # EVIDENCE-OF: R-60814-18273 The R*Tree implementation just makes some
  489. # kinds of queries especially efficient.
  490. #
  491. # The second query is more efficient than the first.
  492. do_vmstep_test 1.2.1 {SELECT * FROM demo_index WHERE +rowid=28269} {$step>2000}
  493. do_vmstep_test 1.2.2 {SELECT * FROM demo_index WHERE rowid=28269} {$step<100}
  494. # EVIDENCE-OF: R-37800-50174 Queries against the primary key are
  495. # efficient: SELECT * FROM demo_index WHERE id=28269;
  496. do_vmstep_test 2.2 { SELECT * FROM demo_index WHERE id=28269 } {$step < 100}
  497. # EVIDENCE-OF: R-35847-18866 The big reason for using an R*Tree is so
  498. # that you can efficiently do range queries against the coordinate
  499. # ranges.
  500. #
  501. # EVIDENCE-OF: R-49927-54202
  502. do_vmstep_test 2.3 {
  503. SELECT id FROM demo_index
  504. WHERE minX<=-80.77470 AND maxX>=-80.77470
  505. AND minY<=35.37785 AND maxY>=35.37785;
  506. } {$step < 100}
  507. # EVIDENCE-OF: R-12823-37176 The query above will quickly locate all
  508. # zipcodes that contain the SQLite main office in their bounding box,
  509. # even if the R*Tree contains many entries.
  510. #
  511. do_execsql_test 2.4 {
  512. SELECT id FROM demo_index
  513. WHERE minX<=-80.77470 AND maxX>=-80.77470
  514. AND minY<=35.37785 AND maxY>=35.37785;
  515. } {
  516. 28322 28269
  517. }
  518. # EVIDENCE-OF: R-07351-00257 For example, to find all zipcode bounding
  519. # boxes that overlap with the 28269 zipcode: SELECT A.id FROM demo_index
  520. # AS A, demo_index AS B WHERE A.maxX>=B.minX AND A.minX<=B.maxX
  521. # AND A.maxY>=B.minY AND A.minY<=B.maxY AND B.id=28269;
  522. #
  523. # Also check that it is efficient
  524. #
  525. # EVIDENCE-OF: R-39094-01937 This second query will find both 28269
  526. # entry (since every bounding box overlaps with itself) and also other
  527. # zipcode that is close enough to 28269 that their bounding boxes
  528. # overlap.
  529. #
  530. # 28269 is there in the result.
  531. #
  532. do_vmstep_test 2.5.1 {
  533. SELECT A.id FROM demo_index AS A, demo_index AS B
  534. WHERE A.maxX>=B.minX AND A.minX<=B.maxX
  535. AND A.maxY>=B.minY AND A.minY<=B.maxY
  536. AND B.id=28269
  537. } {$step < 100}
  538. do_execsql_test 2.5.2 {
  539. SELECT A.id FROM demo_index AS A, demo_index AS B
  540. WHERE A.maxX>=B.minX AND A.minX<=B.maxX
  541. AND A.maxY>=B.minY AND A.minY<=B.maxY
  542. AND B.id=28269 ORDER BY +A.id;
  543. } {
  544. 28215
  545. 28216
  546. 28262
  547. 28269
  548. 28286
  549. 28287
  550. 28291
  551. 28293
  552. 28298
  553. 28313
  554. 28320
  555. 28322
  556. 28336
  557. }
  558. # EVIDENCE-OF: R-02723-34107 Note that it is not necessary for all
  559. # coordinates in an R*Tree index to be constrained in order for the
  560. # index search to be efficient.
  561. #
  562. # EVIDENCE-OF: R-22490-27246 One might, for example, want to query all
  563. # objects that overlap with the 35th parallel: SELECT id FROM demo_index
  564. # WHERE maxY>=35.0 AND minY<=35.0;
  565. do_vmstep_test 2.6.1 {
  566. SELECT id FROM demo_index
  567. WHERE maxY>=35.0 AND minY<=35.0;
  568. } {$step < 100}
  569. do_execsql_test 2.6.2 {
  570. SELECT id FROM demo_index
  571. WHERE maxY>=35.0 AND minY<=35.0;
  572. } {}
  573. #-------------------------------------------------------------------------
  574. #-------------------------------------------------------------------------
  575. # Section 3.4 of documentation.
  576. #-------------------------------------------------------------------------
  577. #-------------------------------------------------------------------------
  578. set testprefix rtreedoc-6
  579. reset_db
  580. # EVIDENCE-OF: R-08327-00674 By default, coordinates are stored in an
  581. # R*Tree using 32-bit floating point values.
  582. #
  583. # EVIDENCE-OF: R-22000-53613 The default virtual table ("rtree") stores
  584. # coordinates as single-precision (4-byte) floating point numbers.
  585. #
  586. # Show this by showing that rounding is consistent with 32-bit float
  587. # rounding.
  588. do_execsql_test 1.0 {
  589. CREATE VIRTUAL TABLE rt USING rtree(id, a,b);
  590. }
  591. do_execsql_test 1.1 {
  592. INSERT INTO rt VALUES(14, -1000000000000, 1000000000000);
  593. SELECT * FROM rt;
  594. } {14 -1000000126976.0 1000000126976.0}
  595. # EVIDENCE-OF: R-39127-51288 When a coordinate cannot be exactly
  596. # represented by a 32-bit floating point number, the lower-bound
  597. # coordinates are rounded down and the upper-bound coordinates are
  598. # rounded up.
  599. foreach {tn val} {
  600. 1 100000000000
  601. 2 200000000000
  602. 3 300000000000
  603. 4 400000000000
  604. 5 -100000000000
  605. 6 -200000000000
  606. 7 -300000000000
  607. 8 -400000000000
  608. } {
  609. set val [expr $val]
  610. do_execsql_test 2.$tn.0 {DELETE FROM rt}
  611. do_execsql_test 2.$tn.1 {INSERT INTO rt VALUES(23, $val, $val)}
  612. do_execsql_test 2.$tn.2 {
  613. SELECT $val>=a, $val<=b, a!=b FROM rt
  614. } {1 1 1}
  615. }
  616. do_execsql_test 3.0 {
  617. DROP TABLE rt;
  618. CREATE VIRTUAL TABLE rt USING rtree(id, x1,x2, y1,y2);
  619. }
  620. # EVIDENCE-OF: R-45870-62834 Thus, bounding boxes might be slightly
  621. # larger than specified, but will never be any smaller.
  622. foreach {tn x1 x2 y1 y2} {
  623. 1 100000000000 200000000000 300000000000 400000000000
  624. } {
  625. set val [expr $val]
  626. do_execsql_test 3.$tn.0 {DELETE FROM rt}
  627. do_execsql_test 3.$tn.1 {INSERT INTO rt VALUES(23, $x1, $x2, $y1, $y2)}
  628. do_execsql_test 3.$tn.2 {
  629. SELECT (x2-x1)*(y2-y1) >= ($x2-$x1)*($y2-$y1) FROM rt
  630. } {1}
  631. }
  632. #-------------------------------------------------------------------------
  633. #-------------------------------------------------------------------------
  634. # Section 3.5 of documentation.
  635. #-------------------------------------------------------------------------
  636. #-------------------------------------------------------------------------
  637. set testprefix rtreedoc-7
  638. reset_db
  639. # EVIDENCE-OF: R-55979-39402 It is the nature of the Guttman R-Tree
  640. # algorithm that any write might radically restructure the tree, and in
  641. # the process change the scan order of the nodes.
  642. #
  643. # In the test below, the INSERT marked "THIS INSERT!!" does not affect
  644. # the results of queries with an ORDER BY, but does affect the results
  645. # of one without an ORDER BY. Therefore the INSERT changed the scan
  646. # order.
  647. do_execsql_test 1.0 {
  648. CREATE VIRTUAL TABLE rt USING rtree(id, minX, maxX);
  649. WITH s(i) AS (
  650. SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<51
  651. )
  652. INSERT INTO rt SELECT NULL, i%10, (i%10)+5 FROM s
  653. }
  654. do_execsql_test 1.1 { SELECT count(*) FROM rt_node } 1
  655. do_test 1.2 {
  656. set res1 [db eval {SELECT * FROM rt WHERE maxX < 30}]
  657. set res1o [db eval {SELECT * FROM rt WHERE maxX < 30 ORDER BY +id}]
  658. db eval { INSERT INTO rt VALUES(NULL, 50, 50) } ;# THIS INSERT!!
  659. set res2 [db eval {SELECT * FROM rt WHERE maxX < 30}]
  660. set res2o [db eval {SELECT * FROM rt WHERE maxX < 30 ORDER BY +id}]
  661. list [expr {$res1==$res2}] [expr {$res1o==$res2o}]
  662. } {0 1}
  663. do_execsql_test 1.3 { SELECT count(*) FROM rt_node } 3
  664. # EVIDENCE-OF: R-00683-48865 For this reason, it is not generally
  665. # possible to modify the R-Tree in the middle of a query of the R-Tree.
  666. # Attempts to do so will fail with a SQLITE_LOCKED "database table is
  667. # locked" error.
  668. #
  669. # SQLITE_LOCKED==6
  670. #
  671. do_test 1.4 {
  672. set nCnt 3
  673. db eval { SELECT * FROM rt WHERE minX>0 AND maxX<12 } {
  674. incr nCnt -1
  675. if {$nCnt==0} {
  676. set rc [catch {db eval {
  677. INSERT INTO rt VALUES(NULL, 51, 51);
  678. }} msg]
  679. set errorcode [db errorcode]
  680. break
  681. }
  682. }
  683. list $errorcode $rc $msg
  684. } {6 1 {database table is locked}}
  685. # EVIDENCE-OF: R-19740-29710 So, for example, suppose an application
  686. # runs one query against an R-Tree like this: SELECT id FROM demo_index
  687. # WHERE maxY>=35.0 AND minY<=35.0; Then for each "id" value
  688. # returned, suppose the application creates an UPDATE statement like the
  689. # following and binds the "id" value returned against the "?1"
  690. # parameter: UPDATE demo_index SET maxY=maxY+0.5 WHERE id=?1;
  691. #
  692. # EVIDENCE-OF: R-52919-32711 Then the UPDATE might fail with an
  693. # SQLITE_LOCKED error.
  694. do_execsql_test 2.0 {
  695. CREATE VIRTUAL TABLE demo_index USING rtree(
  696. id, -- Integer primary key
  697. minX, maxX, -- Minimum and maximum X coordinate
  698. minY, maxY -- Minimum and maximum Y coordinate
  699. );
  700. INSERT INTO demo_index VALUES
  701. (28215, -80.781227, -80.604706, 35.208813, 35.297367),
  702. (28216, -80.957283, -80.840599, 35.235920, 35.367825),
  703. (28217, -80.960869, -80.869431, 35.133682, 35.208233),
  704. (28226, -80.878983, -80.778275, 35.060287, 35.154446);
  705. }
  706. do_test 2.1 {
  707. db eval { SELECT id FROM demo_index WHERE maxY>=35.0 AND minY<=35.0 } {
  708. set rc [catch {
  709. db eval { UPDATE demo_index SET maxY=maxY+0.5 WHERE id=$id }
  710. } msg]
  711. set errorcode [db errorcode]
  712. break
  713. }
  714. list $errorcode $rc $msg
  715. } {6 1 {database table is locked}}
  716. # EVIDENCE-OF: R-32604-49843 Ordinary tables in SQLite are able to read
  717. # and write at the same time.
  718. #
  719. do_execsql_test 3.0 {
  720. CREATE TABLE x1(a INTEGER PRIMARY KEY, b, c);
  721. INSERT INTO x1 VALUES(1, 1, 1);
  722. INSERT INTO x1 VALUES(2, 2, 2);
  723. INSERT INTO x1 VALUES(3, 3, 3);
  724. INSERT INTO x1 VALUES(4, 4, 4);
  725. }
  726. do_test 3.1 {
  727. unset -nocomplain res
  728. set res [list]
  729. db eval { SELECT * FROM x1 } {
  730. lappend res $a $b $c
  731. switch -- $a {
  732. 1 {
  733. db eval { INSERT INTO x1 VALUES(5, 5, 5) }
  734. }
  735. 2 {
  736. db eval { UPDATE x1 SET c=20 WHERE a=2 }
  737. }
  738. 3 {
  739. db eval { DELETE FROM x1 WHERE c IN (3,4) }
  740. }
  741. }
  742. }
  743. set res
  744. } {1 1 1 2 2 2 3 3 3 5 5 5}
  745. do_execsql_test 3.2 {
  746. SELECT * FROM x1
  747. } {1 1 1 2 2 20 5 5 5}
  748. # EVIDENCE-OF: R-06177-00576 And R-Tree can appear to read and write at
  749. # the same time in some circumstances, if it can figure out how to
  750. # reliably run the query to completion before starting the update.
  751. #
  752. # In 8.2, it can, it 8.1, it cannot.
  753. do_test 8.1 {
  754. db eval { SELECT * FROM rt } {
  755. set rc [catch { db eval { INSERT INTO rt VALUES(53,53,53) } } msg]
  756. break;
  757. }
  758. list $rc $msg
  759. } {1 {database table is locked}}
  760. do_test 8.2 {
  761. db eval { SELECT * FROM rt ORDER BY +id } {
  762. set rc [catch { db eval { INSERT INTO rt VALUES(53,53,53) } } msg]
  763. break
  764. }
  765. list $rc $msg
  766. } {0 {}}
  767. #-------------------------------------------------------------------------
  768. #-------------------------------------------------------------------------
  769. # Section 4 of documentation.
  770. #-------------------------------------------------------------------------
  771. #-------------------------------------------------------------------------
  772. set testprefix rtreedoc-8
  773. reset_db
  774. # EVIDENCE-OF: R-21062-30088 For the example above, one might create an
  775. # auxiliary table as follows: CREATE TABLE demo_data( id INTEGER PRIMARY
  776. # KEY, -- primary key objname TEXT, -- name of the object objtype TEXT,
  777. # -- object type boundary BLOB -- detailed boundary of object );
  778. #
  779. # One might.
  780. #
  781. do_execsql_test 1.0 {
  782. CREATE TABLE demo_data(
  783. id INTEGER PRIMARY KEY, -- primary key
  784. objname TEXT, -- name of the object
  785. objtype TEXT, -- object type
  786. boundary BLOB -- detailed boundary of object
  787. );
  788. }
  789. do_execsql_test 1.1 {
  790. CREATE VIRTUAL TABLE demo_index USING rtree(
  791. id, -- Integer primary key
  792. minX, maxX, -- Minimum and maximum X coordinate
  793. minY, maxY -- Minimum and maximum Y coordinate
  794. );
  795. INSERT INTO demo_index VALUES
  796. (28215, -80.781227, -80.604706, 35.208813, 35.297367),
  797. (28216, -80.957283, -80.840599, 35.235920, 35.367825),
  798. (28217, -80.960869, -80.869431, 35.133682, 35.208233),
  799. (28226, -80.878983, -80.778275, 35.060287, 35.154446),
  800. (28227, -80.745544, -80.555382, 35.130215, 35.236916),
  801. (28244, -80.844208, -80.841988, 35.223728, 35.225471),
  802. (28262, -80.809074, -80.682938, 35.276207, 35.377747),
  803. (28269, -80.851471, -80.735718, 35.272560, 35.407925),
  804. (28270, -80.794983, -80.728966, 35.059872, 35.161823),
  805. (28273, -80.994766, -80.875259, 35.074734, 35.172836),
  806. (28277, -80.876793, -80.767586, 35.001709, 35.101063),
  807. (28278, -81.058029, -80.956375, 35.044701, 35.223812),
  808. (28280, -80.844208, -80.841972, 35.225468, 35.227203),
  809. (28282, -80.846382, -80.844193, 35.223972, 35.225655);
  810. INSERT INTO demo_index
  811. SELECT NULL, minX, maxX, minY+0.2, maxY+0.2 FROM demo_index;
  812. INSERT INTO demo_index
  813. SELECT NULL, minX+0.2, maxX+0.2, minY, maxY FROM demo_index;
  814. INSERT INTO demo_index
  815. SELECT NULL, minX, maxX, minY+0.4, maxY+0.4 FROM demo_index;
  816. INSERT INTO demo_index
  817. SELECT NULL, minX+0.4, maxX+0.4, minY, maxY FROM demo_index;
  818. INSERT INTO demo_index
  819. SELECT NULL, minX, maxX, minY+0.8, maxY+0.8 FROM demo_index;
  820. INSERT INTO demo_index
  821. SELECT NULL, minX+0.8, maxX+0.8, minY, maxY FROM demo_index;
  822. INSERT INTO demo_data(id) SELECT id FROM demo_index;
  823. SELECT count(*) FROM demo_index;
  824. } {896}
  825. set ::contained_in 0
  826. proc contained_in {args} {incr ::contained_in ; return 0}
  827. db func contained_in contained_in
  828. # EVIDENCE-OF: R-32671-43888 Then an efficient way to find the specific
  829. # ZIP code for the main SQLite office would be to run a query like this:
  830. # SELECT objname FROM demo_data, demo_index WHERE
  831. # demo_data.id=demo_index.id AND contained_in(demo_data.boundary,
  832. # 35.37785, -80.77470) AND minX<=-80.77470 AND maxX>=-80.77470 AND
  833. # minY<=35.37785 AND maxY>=35.37785;
  834. do_vmstep_test 1.2 {
  835. SELECT objname FROM demo_data, demo_index
  836. WHERE demo_data.id=demo_index.id
  837. AND contained_in(demo_data.boundary, 35.37785, -80.77470)
  838. AND minX<=-80.77470 AND maxX>=-80.77470
  839. AND minY<=35.37785 AND maxY>=35.37785;
  840. } {$step<100}
  841. set ::contained_in1 $::contained_in
  842. # EVIDENCE-OF: R-32761-23915 One would get the same answer without the
  843. # use of the R*Tree index using the following simpler query: SELECT
  844. # objname FROM demo_data WHERE contained_in(demo_data.boundary,
  845. # 35.37785, -80.77470);
  846. set ::contained_in 0
  847. do_vmstep_test 1.3 {
  848. SELECT objname FROM demo_data
  849. WHERE contained_in(demo_data.boundary, 35.37785, -80.77470);
  850. } {$step>3200}
  851. # EVIDENCE-OF: R-40261-32799 The problem with this latter query is that
  852. # it must apply the contained_in() function to all entries in the
  853. # demo_data table.
  854. #
  855. # 896 of them, IIRC.
  856. do_test 1.4 {
  857. set ::contained_in
  858. } 896
  859. # EVIDENCE-OF: R-24212-52761 The use of the R*Tree in the penultimate
  860. # query reduces the number of calls to contained_in() function to a
  861. # small subset of the entire table.
  862. #
  863. # 2 is a small subset of 896.
  864. #
  865. # EVIDENCE-OF: R-39057-63901 The R*Tree index did not find the exact
  866. # answer itself, it merely limited the search space.
  867. #
  868. # contained_in() filtered out those 2 rows.
  869. do_test 1.5 {
  870. set ::contained_in1
  871. } {2}
  872. #-------------------------------------------------------------------------
  873. #-------------------------------------------------------------------------
  874. # Section 4.1 of documentation.
  875. #-------------------------------------------------------------------------
  876. #-------------------------------------------------------------------------
  877. set testprefix rtreedoc-9
  878. reset_db
  879. # EVIDENCE-OF: R-46566-43213 Beginning with SQLite version 3.24.0
  880. # (2018-06-04), r-tree tables can have auxiliary columns that store
  881. # arbitrary data. Auxiliary columns can be used in place of secondary
  882. # tables such as "demo_data".
  883. #
  884. # EVIDENCE-OF: R-41287-48160 Auxiliary columns are marked with a "+"
  885. # symbol before the column name.
  886. #
  887. # This interface cannot conveniently be used to prove anything about
  888. # versions of SQLite prior to 3.24.0.
  889. #
  890. do_execsql_test 1.0 {
  891. CREATE VIRTUAL TABLE rta USING rtree(
  892. id, u1,u2, v1,v2, +aux
  893. );
  894. INSERT INTO rta(aux) VALUES(NULL);
  895. INSERT INTO rta(aux) VALUES(45);
  896. INSERT INTO rta(aux) VALUES(22.3);
  897. INSERT INTO rta(aux) VALUES('hello');
  898. INSERT INTO rta(aux) VALUES(X'ABCD');
  899. SELECT typeof(aux), quote(aux) FROM rta;
  900. } {
  901. null NULL
  902. integer 45
  903. real 22.3
  904. text 'hello'
  905. blob X'ABCD'
  906. }
  907. # EVIDENCE-OF: R-30514-26093 Auxiliary columns must come after all of
  908. # the coordinate boundary columns.
  909. foreach {tn cols} {
  910. 1 "id x1,x2, +extra, y1,y2"
  911. 2 "extra, +id x1,x2, y1,y2"
  912. 3 "id, x1,+x2, extra, y1,y2"
  913. } {
  914. do_catchsql_test 2.$tn "
  915. CREATE VIRTUAL TABLE rrr USING rtree($cols)
  916. " {1 {Auxiliary rtree columns must be last}}
  917. }
  918. do_catchsql_test 3.0 {
  919. CREATE VIRTUAL TABLE rrr USING rtree(+id, extra, x1, x2);
  920. } {1 {near "+": syntax error}}
  921. # EVIDENCE-OF: R-01280-03635 An RTREE table can have no more than 100
  922. # columns total. In other words, the count of columns including the
  923. # integer primary key column, the coordinate boundary columns, and all
  924. # auxiliary columns must be 100 or less.
  925. do_catchsql_test 3.1 {
  926. CREATE VIRTUAL TABLE r1 USING rtree(intid, u1,u2,
  927. +c00, +c01, +c02, +c03, +c04, +c05, +c06, +c07, +c08, +c09,
  928. +c10, +c11, +c12, +c13, +c14, +c15, +c16, +c17, +c18, +c19,
  929. +c20, +c21, +c22, +c23, +c24, +c25, +c26, +c27, +c28, +c29,
  930. +c30, +c31, +c32, +c33, +c34, +c35, +c36, +c37, +c38, +c39,
  931. +c40, +c41, +c42, +c43, +c44, +c45, +c46, +c47, +c48, +c49,
  932. +c50, +c51, +c52, +c53, +c54, +c55, +c56, +c57, +c58, +c59,
  933. +c60, +c61, +c62, +c63, +c64, +c65, +c66, +c67, +c68, +c69,
  934. +c70, +c71, +c72, +c73, +c74, +c75, +c76, +c77, +c78, +c79,
  935. +c80, +c81, +c82, +c83, +c84, +c85, +c86, +c87, +c88, +c89,
  936. +c90, +c91, +c92, +c93, +c94, +c95, +c96
  937. );
  938. } {0 {}}
  939. do_catchsql_test 3.2 {
  940. DROP TABLE r1;
  941. CREATE VIRTUAL TABLE r1 USING rtree(intid, u1,u2,
  942. +c00, +c01, +c02, +c03, +c04, +c05, +c06, +c07, +c08, +c09,
  943. +c10, +c11, +c12, +c13, +c14, +c15, +c16, +c17, +c18, +c19,
  944. +c20, +c21, +c22, +c23, +c24, +c25, +c26, +c27, +c28, +c29,
  945. +c30, +c31, +c32, +c33, +c34, +c35, +c36, +c37, +c38, +c39,
  946. +c40, +c41, +c42, +c43, +c44, +c45, +c46, +c47, +c48, +c49,
  947. +c50, +c51, +c52, +c53, +c54, +c55, +c56, +c57, +c58, +c59,
  948. +c60, +c61, +c62, +c63, +c64, +c65, +c66, +c67, +c68, +c69,
  949. +c70, +c71, +c72, +c73, +c74, +c75, +c76, +c77, +c78, +c79,
  950. +c80, +c81, +c82, +c83, +c84, +c85, +c86, +c87, +c88, +c89,
  951. +c90, +c91, +c92, +c93, +c94, +c95, +c96, +c97
  952. );
  953. } {1 {Too many columns for an rtree table}}
  954. do_catchsql_test 3.3 {
  955. CREATE VIRTUAL TABLE r1 USING rtree(intid, u1,u2, v1,v2,
  956. +c00, +c01, +c02, +c03, +c04, +c05, +c06, +c07, +c08, +c09,
  957. +c10, +c11, +c12, +c13, +c14, +c15, +c16, +c17, +c18, +c19,
  958. +c20, +c21, +c22, +c23, +c24, +c25, +c26, +c27, +c28, +c29,
  959. +c30, +c31, +c32, +c33, +c34, +c35, +c36, +c37, +c38, +c39,
  960. +c40, +c41, +c42, +c43, +c44, +c45, +c46, +c47, +c48, +c49,
  961. +c50, +c51, +c52, +c53, +c54, +c55, +c56, +c57, +c58, +c59,
  962. +c60, +c61, +c62, +c63, +c64, +c65, +c66, +c67, +c68, +c69,
  963. +c70, +c71, +c72, +c73, +c74, +c75, +c76, +c77, +c78, +c79,
  964. +c80, +c81, +c82, +c83, +c84, +c85, +c86, +c87, +c88, +c89,
  965. +c90, +c91, +c92, +c93, +c94,
  966. );
  967. } {0 {}}
  968. do_catchsql_test 3.4 {
  969. DROP TABLE r1;
  970. CREATE VIRTUAL TABLE r1 USING rtree(intid, u1,u2, v1,v2,
  971. +c00, +c01, +c02, +c03, +c04, +c05, +c06, +c07, +c08, +c09,
  972. +c10, +c11, +c12, +c13, +c14, +c15, +c16, +c17, +c18, +c19,
  973. +c20, +c21, +c22, +c23, +c24, +c25, +c26, +c27, +c28, +c29,
  974. +c30, +c31, +c32, +c33, +c34, +c35, +c36, +c37, +c38, +c39,
  975. +c40, +c41, +c42, +c43, +c44, +c45, +c46, +c47, +c48, +c49,
  976. +c50, +c51, +c52, +c53, +c54, +c55, +c56, +c57, +c58, +c59,
  977. +c60, +c61, +c62, +c63, +c64, +c65, +c66, +c67, +c68, +c69,
  978. +c70, +c71, +c72, +c73, +c74, +c75, +c76, +c77, +c78, +c79,
  979. +c80, +c81, +c82, +c83, +c84, +c85, +c86, +c87, +c88, +c89,
  980. +c90, +c91, +c92, +c93, +c94, +c95,
  981. );
  982. } {1 {Too many columns for an rtree table}}
  983. # EVIDENCE-OF: R-05552-15084
  984. do_execsql_test 4.0 {
  985. CREATE VIRTUAL TABLE demo_index2 USING rtree(
  986. id, -- Integer primary key
  987. minX, maxX, -- Minimum and maximum X coordinate
  988. minY, maxY, -- Minimum and maximum Y coordinate
  989. +objname TEXT, -- name of the object
  990. +objtype TEXT, -- object type
  991. +boundary BLOB -- detailed boundary of object
  992. );
  993. }
  994. do_execsql_test 4.1 {
  995. CREATE VIRTUAL TABLE demo_index USING rtree(
  996. id, -- Integer primary key
  997. minX, maxX, -- Minimum and maximum X coordinate
  998. minY, maxY -- Minimum and maximum Y coordinate
  999. );
  1000. CREATE TABLE demo_data(
  1001. id INTEGER PRIMARY KEY, -- primary key
  1002. objname TEXT, -- name of the object
  1003. objtype TEXT, -- object type
  1004. boundary BLOB -- detailed boundary of object
  1005. );
  1006. INSERT INTO demo_index2(id) VALUES(1);
  1007. INSERT INTO demo_index(id) VALUES(1);
  1008. INSERT INTO demo_data(id) VALUES(1);
  1009. }
  1010. do_test 4.2 {
  1011. catch { array unset R }
  1012. db eval {SELECT * FROM demo_index2} R { set r1 [array names R] }
  1013. catch { array unset R }
  1014. db eval {SELECT * FROM demo_index NATURAL JOIN demo_data } R {
  1015. set r2 [array names R]
  1016. }
  1017. expr {$r1==$r2}
  1018. } {1}
  1019. # EVIDENCE-OF: R-26099-32169 SELECT objname FROM demo_index2 WHERE
  1020. # contained_in(boundary, 35.37785, -80.77470) AND minX<=-80.77470 AND
  1021. # maxX>=-80.77470 AND minY<=35.37785 AND maxY>=35.37785;
  1022. do_execsql_test 4.3.1 {
  1023. DELETE FROM demo_index2;
  1024. INSERT INTO demo_index2(id,minX,maxX,minY,maxY) VALUES
  1025. (28215, -80.781227, -80.604706, 35.208813, 35.297367),
  1026. (28216, -80.957283, -80.840599, 35.235920, 35.367825),
  1027. (28217, -80.960869, -80.869431, 35.133682, 35.208233),
  1028. (28226, -80.878983, -80.778275, 35.060287, 35.154446),
  1029. (28227, -80.745544, -80.555382, 35.130215, 35.236916),
  1030. (28244, -80.844208, -80.841988, 35.223728, 35.225471),
  1031. (28262, -80.809074, -80.682938, 35.276207, 35.377747),
  1032. (28269, -80.851471, -80.735718, 35.272560, 35.407925),
  1033. (28270, -80.794983, -80.728966, 35.059872, 35.161823),
  1034. (28273, -80.994766, -80.875259, 35.074734, 35.172836),
  1035. (28277, -80.876793, -80.767586, 35.001709, 35.101063),
  1036. (28278, -81.058029, -80.956375, 35.044701, 35.223812),
  1037. (28280, -80.844208, -80.841972, 35.225468, 35.227203),
  1038. (28282, -80.846382, -80.844193, 35.223972, 35.225655);
  1039. }
  1040. set ::contained_in 0
  1041. proc contained_in {args} {
  1042. incr ::contained_in
  1043. return 0
  1044. }
  1045. db func contained_in contained_in
  1046. do_execsql_test 4.3.2 {
  1047. SELECT objname FROM demo_index2
  1048. WHERE contained_in(boundary, 35.37785, -80.77470)
  1049. AND minX<=-80.77470 AND maxX>=-80.77470
  1050. AND minY<=35.37785 AND maxY>=35.37785;
  1051. }
  1052. do_test 4.3.3 {
  1053. # Function invoked only once because r-tree filtering happened first.
  1054. set ::contained_in
  1055. } 1
  1056. set ::contained_in 0
  1057. do_execsql_test 4.3.4 {
  1058. SELECT objname FROM demo_index2
  1059. WHERE contained_in(boundary, 35.37785, -80.77470)
  1060. }
  1061. do_test 4.3.3 {
  1062. # Function invoked 14 times because no r-tree filtering. Inefficient.
  1063. set ::contained_in
  1064. } 14
  1065. #-------------------------------------------------------------------------
  1066. #-------------------------------------------------------------------------
  1067. # Section 4.1.1 of documentation.
  1068. #-------------------------------------------------------------------------
  1069. #-------------------------------------------------------------------------
  1070. set testprefix rtreedoc-9
  1071. reset_db
  1072. # EVIDENCE-OF: R-24021-02490 For auxiliary columns, only the name of the
  1073. # column matters. The type affinity is ignored.
  1074. #
  1075. # EVIDENCE-OF: R-39906-44154 Constraints such as NOT NULL, UNIQUE,
  1076. # REFERENCES, or CHECK are also ignored.
  1077. do_execsql_test 1.0 { PRAGMA foreign_keys = on }
  1078. foreach {tn auxcol nm} {
  1079. 1 "+extra INTEGER" extra
  1080. 2 "+extra TEXT" extra
  1081. 3 "+extra BLOB" extra
  1082. 4 "+extra REAL" extra
  1083. 5 "+col NOT NULL" col
  1084. 6 "+col CHECK (col IS NOT NULL)" col
  1085. 7 "+col REFERENCES tbl(x)" col
  1086. } {
  1087. do_execsql_test 1.$tn.1 "
  1088. CREATE VIRTUAL TABLE rt USING rtree_i32(k, a,b, $auxcol)
  1089. "
  1090. # Check that the aux column has no affinity. Or NOT NULL constraint.
  1091. # And that the aux column is the child key of an FK constraint.
  1092. #
  1093. do_execsql_test 1.$tn.2 "
  1094. INSERT INTO rt($nm) VALUES(NULL), (45), (-123.2), ('456'), (X'ABCD');
  1095. SELECT typeof($nm), quote($nm) FROM rt;
  1096. " {
  1097. null NULL
  1098. integer 45
  1099. real -123.2
  1100. text '456'
  1101. blob X'ABCD'
  1102. }
  1103. # Check that there is no UNIQUE constraint either.
  1104. #
  1105. do_execsql_test 1.$tn.3 "
  1106. INSERT INTO rt($nm) VALUES('xyz'), ('xyz'), ('xyz');
  1107. "
  1108. do_execsql_test 1.$tn.2 {
  1109. DROP TABLE rt
  1110. }
  1111. }
  1112. #-------------------------------------------------------------------------
  1113. #-------------------------------------------------------------------------
  1114. # Section 5 of documentation.
  1115. #-------------------------------------------------------------------------
  1116. #-------------------------------------------------------------------------
  1117. set testprefix rtreedoc-10
  1118. # EVIDENCE-OF: R-21011-43790 If integer coordinates are desired, declare
  1119. # the table using "rtree_i32" instead: CREATE VIRTUAL TABLE intrtree
  1120. # USING rtree_i32(id,x0,x1,y0,y1,z0,z1);
  1121. do_execsql_test 1.0 {
  1122. CREATE VIRTUAL TABLE intrtree USING rtree_i32(id,x0,x1,y0,y1,z0,z1);
  1123. INSERT INTO intrtree DEFAULT VALUES;
  1124. SELECT typeof(x0) FROM intrtree;
  1125. } {integer}
  1126. # EVIDENCE-OF: R-09193-49806 An rtree_i32 stores coordinates as 32-bit
  1127. # signed integers.
  1128. #
  1129. # Show that coordinates are cast in a way consistent with casting to
  1130. # a signed 32-bit integer.
  1131. do_execsql_test 1.1 {
  1132. DELETE FROM intrtree;
  1133. INSERT INTO intrtree VALUES(333,
  1134. 1<<44, (1<<44)+1,
  1135. 10000000000, 10000000001,
  1136. -10000000001, -10000000000
  1137. );
  1138. SELECT * FROM intrtree;
  1139. } {
  1140. 333 0 1 1410065408 1410065409 -1410065409 -1410065408
  1141. }
  1142. #-------------------------------------------------------------------------
  1143. #-------------------------------------------------------------------------
  1144. # Section 7.1 of documentation.
  1145. #-------------------------------------------------------------------------
  1146. #-------------------------------------------------------------------------
  1147. set testprefix rtreedoc-11
  1148. reset_db
  1149. # This command assumes that the argument is a node blob for a 2 dimensional
  1150. # i32 r-tree table. It decodes and returns a list of cells from the node
  1151. # as a list. Each cell is itself a list of the following form:
  1152. #
  1153. # {$rowid $minX $maxX $minY $maxY}
  1154. #
  1155. # For internal (non-leaf) nodes, the rowid is replaced by the child node
  1156. # number.
  1157. #
  1158. proc rnode {aData} {
  1159. set nDim 2
  1160. set nData [string length $aData]
  1161. set nBytePerCell [expr (8 + 2*$nDim*4)]
  1162. binary scan [string range $aData 2 3] S nCell
  1163. set res [list]
  1164. for {set i 0} {$i < $nCell} {incr i} {
  1165. set iOff [expr $i*$nBytePerCell+4]
  1166. set cell [string range $aData $iOff [expr $iOff+$nBytePerCell-1]]
  1167. binary scan $cell WIIII rowid x1 x2 y1 y2
  1168. lappend res [list $rowid $x1 $x2 $y1 $y2]
  1169. }
  1170. return $res
  1171. }
  1172. # aData must be a node blob. This command returns true if the node contains
  1173. # rowid $rowid, or false otherwise.
  1174. #
  1175. proc rnode_contains {aData rowid} {
  1176. set L [rnode $aData]
  1177. foreach cell $L {
  1178. set r [lindex $cell 0]
  1179. if {$r==$rowid} { return 1 }
  1180. }
  1181. return 0
  1182. }
  1183. proc rnode_replace_cell {aData iCell cell} {
  1184. set aCell [binary format WIIII {*}$cell]
  1185. set nDim 2
  1186. set nBytePerCell [expr (8 + 2*$nDim*4)]
  1187. set iOff [expr $iCell*$nBytePerCell+4]
  1188. set aNew [binary format a*a*a* \
  1189. [string range $aData 0 $iOff-1] \
  1190. $aCell \
  1191. [string range $aData $iOff+$nBytePerCell end] \
  1192. ]
  1193. return $aNew
  1194. }
  1195. db function rnode rnode
  1196. db function rnode_contains rnode_contains
  1197. db function rnode_replace_cell rnode_replace_cell
  1198. foreach {tn nm} {
  1199. 1 x1
  1200. 2 asdfghjkl
  1201. 3 hello_world
  1202. } {
  1203. do_execsql_test 1.$tn.1 "
  1204. CREATE VIRTUAL TABLE $nm USING rtree(a,b,c,d,e);
  1205. "
  1206. # EVIDENCE-OF: R-33789-46762 The content of an R*Tree index is actually
  1207. # stored in three ordinary SQLite tables with names derived from the
  1208. # name of the R*Tree.
  1209. #
  1210. # EVIDENCE-OF: R-39849-06566 This is their schema: CREATE TABLE
  1211. # %_node(nodeno INTEGER PRIMARY KEY, data) CREATE TABLE %_parent(nodeno
  1212. # INTEGER PRIMARY KEY, parentnode) CREATE TABLE %_rowid(rowid INTEGER
  1213. # PRIMARY KEY, nodeno)
  1214. #
  1215. # EVIDENCE-OF: R-07489-10051 The "%" in the name of each shadow table is
  1216. # replaced by the name of the R*Tree virtual table. So, if the name of
  1217. # the R*Tree table is "xyz" then the three shadow tables would be
  1218. # "xyz_node", "xyz_parent", and "xyz_rowid".
  1219. do_execsql_test 1.$tn.2 {
  1220. SELECT sql FROM sqlite_schema WHERE name!=$nm ORDER BY 1
  1221. } [string map [list % $nm] "
  1222. {CREATE TABLE \"%_node\"(nodeno INTEGER PRIMARY KEY,data)}
  1223. {CREATE TABLE \"%_parent\"(nodeno INTEGER PRIMARY KEY,parentnode)}
  1224. {CREATE TABLE \"%_rowid\"(rowid INTEGER PRIMARY KEY,nodeno)}
  1225. "]
  1226. do_execsql_test 1.$tn "DROP TABLE $nm"
  1227. }
  1228. # EVIDENCE-OF: R-51070-59303 There is one entry in the %_node table for
  1229. # each R*Tree node.
  1230. #
  1231. # The following creates a 6 node r-tree structure.
  1232. #
  1233. do_execsql_test 2.0 {
  1234. CREATE VIRTUAL TABLE r1 USING rtree_i32(i, x1,x2, y1,y2);
  1235. WITH t(i) AS (
  1236. VALUES(1) UNION SELECT i+1 FROM t WHERE i<110
  1237. )
  1238. INSERT INTO r1 SELECT i, (i%10), (i%10)+2, (i%6), (i%7)+6 FROM t;
  1239. }
  1240. do_execsql_test 2.1 {
  1241. SELECT count(*) FROM r1_node;
  1242. } 6
  1243. # EVIDENCE-OF: R-27261-09153 All nodes other than the root have an entry
  1244. # in the %_parent shadow table that identifies the parent node.
  1245. #
  1246. # In this case nodes 2-6 are the children of node 1.
  1247. #
  1248. do_execsql_test 2.3 {
  1249. SELECT nodeno, parentnode FROM r1_parent
  1250. } {2 1 3 1 4 1 5 1 6 1}
  1251. # EVIDENCE-OF: R-02358-35037 The %_rowid shadow table maps entry rowids
  1252. # to the node that contains that entry.
  1253. #
  1254. do_execsql_test 2.4 {
  1255. SELECT 'failed' FROM r1_rowid WHERE 0==rnode_contains(
  1256. (SELECT data FROM r1_node WHERE nodeno=r1_rowid.nodeno), rowid
  1257. )
  1258. }
  1259. do_test 2.5 {
  1260. db eval { SELECT nodeno, data FROM r1_node WHERE nodeno!=1 } {
  1261. set L [rnode $data]
  1262. foreach cell $L {
  1263. set rowid [lindex $cell 0]
  1264. set rowid_nodeno 0
  1265. db eval {SELECT nodeno AS rowid_nodeno FROM r1_rowid WHERE rowid=$rowid} {
  1266. break
  1267. }
  1268. if {$rowid_nodeno!=$nodeno} { error "data mismatch!" }
  1269. }
  1270. }
  1271. } {}
  1272. # EVIDENCE-OF: R-65201-22208 Extra columns appended to the %_rowid table
  1273. # hold the content of auxiliary columns.
  1274. #
  1275. # EVIDENCE-OF: R-44161-28345 The names of these extra %_rowid columns
  1276. # are probably not the same as the actual auxiliary column names.
  1277. #
  1278. # In this case, the auxiliary columns are named "e1" and "e2". The
  1279. # extra %_rowid columns are named "a0" and "a1".
  1280. #
  1281. do_execsql_test 3.0 {
  1282. CREATE VIRTUAL TABLE rtaux USING rtree(id, x1,x2, y1,y2, +e1, +e2);
  1283. SELECT sql FROM sqlite_schema WHERE name='rtaux_rowid';
  1284. } {
  1285. {CREATE TABLE "rtaux_rowid"(rowid INTEGER PRIMARY KEY,nodeno,a0,a1)}
  1286. }
  1287. do_execsql_test 3.1 {
  1288. INSERT INTO rtaux(e1, e2) VALUES('hello', 'world'), (123, 456);
  1289. }
  1290. do_execsql_test 3.2 {
  1291. SELECT a0, a1 FROM rtaux_rowid;
  1292. } {
  1293. hello world 123 456
  1294. }
  1295. #-------------------------------------------------------------------------
  1296. #-------------------------------------------------------------------------
  1297. # Section 7.2 of documentation.
  1298. #-------------------------------------------------------------------------
  1299. #-------------------------------------------------------------------------
  1300. set testprefix rtreedoc-12
  1301. reset_db
  1302. forcedelete test.db2
  1303. db function rnode rnode
  1304. db function rnode_contains rnode_contains
  1305. db function rnode_replace_cell rnode_replace_cell
  1306. # EVIDENCE-OF: R-13571-45795 The scalar SQL function rtreecheck(R) or
  1307. # rtreecheck(S,R) runs an integrity check on the rtree table named R
  1308. # contained within database S.
  1309. #
  1310. # EVIDENCE-OF: R-36011-59963 The function returns a human-language
  1311. # description of any problems found, or the string 'ok' if everything is
  1312. # ok.
  1313. #
  1314. do_execsql_test 1.0 {
  1315. CREATE VIRTUAL TABLE rt1 USING rtree(id, a, b);
  1316. WITH s(i) AS (
  1317. VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<200
  1318. )
  1319. INSERT INTO rt1 SELECT i, i, i FROM s;
  1320. ATTACH 'test.db2' AS 'aux';
  1321. CREATE VIRTUAL TABLE aux.rt1 USING rtree(id, a, b);
  1322. INSERT INTO aux.rt1 SELECT * FROM rt1;
  1323. }
  1324. do_execsql_test 1.1.1 { SELECT rtreecheck('rt1'); } {ok}
  1325. do_execsql_test 1.1.2 { SELECT rtreecheck('main', 'rt1'); } {ok}
  1326. do_execsql_test 1.1.3 { SELECT rtreecheck('aux', 'rt1'); } {ok}
  1327. do_catchsql_test 1.1.4 {
  1328. SELECT rtreecheck('nosuchdb', 'rt1');
  1329. } {1 {SQL logic error}}
  1330. # Corrupt the table in database 'main':
  1331. do_execsql_test 1.2.1 { UPDATE rt1_node SET nodeno=21 WHERE nodeno=3; }
  1332. do_execsql_test 1.2.1 { SELECT rtreecheck('rt1')=='ok'; } {0}
  1333. do_execsql_test 1.2.2 { SELECT rtreecheck('main', 'rt1')=='ok'; } {0}
  1334. do_execsql_test 1.2.3 { SELECT rtreecheck('aux', 'rt1')=='ok'; } {1}
  1335. do_execsql_test 1.2.4 { UPDATE rt1_node SET nodeno=3 WHERE nodeno=21; }
  1336. # Corrupt the table in database 'aux':
  1337. do_execsql_test 1.2.1 { UPDATE aux.rt1_node SET nodeno=21 WHERE nodeno=3; }
  1338. do_execsql_test 1.2.1 { SELECT rtreecheck('rt1')=='ok'; } {1}
  1339. do_execsql_test 1.2.2 { SELECT rtreecheck('main', 'rt1')=='ok'; } {1}
  1340. do_execsql_test 1.2.3 { SELECT rtreecheck('aux', 'rt1')=='ok'; } {0}
  1341. do_execsql_test 1.2.4 { UPDATE rt1_node SET nodeno=3 WHERE nodeno=21; }
  1342. # EVIDENCE-OF: R-45759-33459 Example: To verify that an R*Tree named
  1343. # "demo_index" is well-formed and internally consistent, run: SELECT
  1344. # rtreecheck('demo_index');
  1345. do_execsql_test 2.0 {
  1346. CREATE VIRTUAL TABLE demo_index USING rtree(id, x1,x2, y1,y2);
  1347. INSERT INTO demo_index SELECT id, a, b, a, b FROM rt1;
  1348. }
  1349. do_execsql_test 2.1 { SELECT rtreecheck('demo_index') } {ok}
  1350. do_execsql_test 2.2 {
  1351. UPDATE demo_index_rowid SET nodeno=44 WHERE rowid=44;
  1352. SELECT rtreecheck('demo_index');
  1353. } {{Found (44 -> 44) in %_rowid table, expected (44 -> 4)}}
  1354. do_execsql_test 3.0 {
  1355. CREATE VIRTUAL TABLE rt2 USING rtree_i32(id, a, b, c, d);
  1356. WITH s(i) AS (
  1357. VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<200
  1358. )
  1359. INSERT INTO rt2 SELECT i, i, i+2, i, i+2 FROM s;
  1360. }
  1361. # EVIDENCE-OF: R-02555-31045 for each dimension, (coord1 <= coord2).
  1362. #
  1363. execsql BEGIN
  1364. do_test 3.1 {
  1365. set cell [
  1366. lindex [execsql {SELECT rnode(data) FROM rt2_node WHERE nodeno=3}] 0 3
  1367. ]
  1368. set cell [list [lindex $cell 0] \
  1369. [lindex $cell 2] [lindex $cell 1] \
  1370. [lindex $cell 3] [lindex $cell 4] \
  1371. ]
  1372. execsql {
  1373. UPDATE rt2_node SET data=rnode_replace_cell(data, 3, $cell) WHERE nodeno=3
  1374. }
  1375. execsql { SELECT rtreecheck('rt2') }
  1376. } {{Dimension 0 of cell 3 on node 3 is corrupt}}
  1377. execsql ROLLBACK
  1378. # EVIDENCE-OF: R-13844-15873 unless the cell is on the root node, that
  1379. # the cell is bounded by the parent cell on the parent node.
  1380. #
  1381. execsql BEGIN
  1382. do_test 3.2 {
  1383. set cell [
  1384. lindex [execsql {SELECT rnode(data) FROM rt2_node WHERE nodeno=3}] 0 3
  1385. ]
  1386. lset cell 3 450
  1387. lset cell 4 451
  1388. execsql {
  1389. UPDATE rt2_node SET data=rnode_replace_cell(data, 3, $cell) WHERE nodeno=3
  1390. }
  1391. execsql { SELECT rtreecheck('rt2') }
  1392. } {{Dimension 1 of cell 3 on node 3 is corrupt relative to parent}}
  1393. execsql ROLLBACK
  1394. # EVIDENCE-OF: R-02505-03621 for leaf nodes, that there is an entry in
  1395. # the %_rowid table corresponding to the cell's rowid value that points
  1396. # to the correct node.
  1397. #
  1398. execsql BEGIN
  1399. do_test 3.3 {
  1400. execsql {
  1401. UPDATE rt2_rowid SET rowid=452 WHERE rowid=100
  1402. }
  1403. execsql { SELECT rtreecheck('rt2') }
  1404. } {{Mapping (100 -> 6) missing from %_rowid table}}
  1405. execsql ROLLBACK
  1406. # EVIDENCE-OF: R-50927-02218 for cells on non-leaf nodes, that there is
  1407. # an entry in the %_parent table mapping from the cell's child node to
  1408. # the node that it resides on.
  1409. #
  1410. execsql BEGIN
  1411. do_test 3.4.1 {
  1412. execsql {
  1413. UPDATE rt2_parent SET parentnode=123 WHERE nodeno=3
  1414. }
  1415. execsql { SELECT rtreecheck('rt2') }
  1416. } {{Found (3 -> 123) in %_parent table, expected (3 -> 1)}}
  1417. execsql ROLLBACK
  1418. execsql BEGIN
  1419. do_test 3.4.2 {
  1420. execsql {
  1421. UPDATE rt2_parent SET nodeno=123 WHERE nodeno=3
  1422. }
  1423. execsql { SELECT rtreecheck('rt2') }
  1424. } {{Mapping (3 -> 1) missing from %_parent table}}
  1425. execsql ROLLBACK
  1426. # EVIDENCE-OF: R-23235-09153 That there are the same number of entries
  1427. # in the %_rowid table as there are leaf cells in the r-tree structure,
  1428. # and that there is a leaf cell that corresponds to each entry in the
  1429. # %_rowid table.
  1430. execsql BEGIN
  1431. do_test 3.5 {
  1432. execsql { INSERT INTO rt2_rowid VALUES(1000, 1000) }
  1433. execsql { SELECT rtreecheck('rt2') }
  1434. } {{Wrong number of entries in %_rowid table - expected 200, actual 201}}
  1435. execsql ROLLBACK
  1436. # EVIDENCE-OF: R-62800-43436 That there are the same number of entries
  1437. # in the %_parent table as there are non-leaf cells in the r-tree
  1438. # structure, and that there is a non-leaf cell that corresponds to each
  1439. # entry in the %_parent table.
  1440. execsql BEGIN
  1441. do_test 3.6 {
  1442. execsql { INSERT INTO rt2_parent VALUES(1000, 1000) }
  1443. execsql { SELECT rtreecheck('rt2') }
  1444. } {{Wrong number of entries in %_parent table - expected 10, actual 11}}
  1445. execsql ROLLBACK
  1446. finish_test