btree.test 22 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018
  1. # 2001 September 15
  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. # This file implements regression tests for SQLite library. The
  12. # focus of this script is btree database backend
  13. #
  14. # $Id: btree.test,v 1.12 2002/02/19 13:39:23 drh Exp $
  15. set testdir [file dirname $argv0]
  16. source $testdir/tester.tcl
  17. if {[info commands btree_open]!=""} {
  18. # Basic functionality. Open and close a database.
  19. #
  20. do_test btree-1.1 {
  21. file delete -force test1.bt
  22. file delete -force test1.bt-journal
  23. set rc [catch {btree_open test1.bt} ::b1]
  24. } {0}
  25. # The second element of the list returned by btree_pager_stats is the
  26. # number of pages currently checked out. We'll be checking this value
  27. # frequently during this test script, to make sure the btree library
  28. # is properly releasing the pages it checks out, and thus avoiding
  29. # page leaks.
  30. #
  31. do_test btree-1.1.1 {
  32. lindex [btree_pager_stats $::b1] 1
  33. } {0}
  34. do_test btree-1.2 {
  35. set rc [catch {btree_open test1.bt} ::b2]
  36. } {0}
  37. do_test btree-1.3 {
  38. set rc [catch {btree_close $::b2} msg]
  39. lappend rc $msg
  40. } {0 {}}
  41. # Do an insert and verify that the database file grows in size.
  42. #
  43. do_test btree-1.4 {
  44. set rc [catch {btree_begin_transaction $::b1} msg]
  45. lappend rc $msg
  46. } {0 {}}
  47. do_test btree-1.4.1 {
  48. lindex [btree_pager_stats $::b1] 1
  49. } {1}
  50. do_test btree-1.5 {
  51. set rc [catch {btree_cursor $::b1 2 1} ::c1]
  52. if {$rc} {lappend rc $::c1}
  53. set rc
  54. } {0}
  55. do_test btree-1.6 {
  56. set rc [catch {btree_insert $::c1 one 1.00} msg]
  57. lappend rc $msg
  58. } {0 {}}
  59. do_test btree-1.7 {
  60. btree_key $::c1
  61. } {one}
  62. do_test btree-1.8 {
  63. btree_data $::c1
  64. } {1.00}
  65. do_test btree-1.9 {
  66. set rc [catch {btree_close_cursor $::c1} msg]
  67. lappend rc $msg
  68. } {0 {}}
  69. do_test btree-1.10 {
  70. set rc [catch {btree_commit $::b1} msg]
  71. lappend rc $msg
  72. } {0 {}}
  73. do_test btree-1.11 {
  74. file size test1.bt
  75. } {2048}
  76. do_test btree-1.12 {
  77. lindex [btree_pager_stats $::b1] 1
  78. } {0}
  79. # Reopen the database and attempt to read the record that we wrote.
  80. #
  81. do_test btree-2.1 {
  82. set rc [catch {btree_cursor $::b1 2 1} ::c1]
  83. if {$rc} {lappend rc $::c1}
  84. set rc
  85. } {0}
  86. do_test btree-2.2 {
  87. btree_move_to $::c1 abc
  88. } {1}
  89. do_test btree-2.3 {
  90. btree_move_to $::c1 xyz
  91. } {-1}
  92. do_test btree-2.4 {
  93. btree_move_to $::c1 one
  94. } {0}
  95. do_test btree-2.5 {
  96. btree_key $::c1
  97. } {one}
  98. do_test btree-2.6 {
  99. btree_data $::c1
  100. } {1.00}
  101. do_test btree-2.7 {
  102. lindex [btree_pager_stats $::b1] 1
  103. } {2}
  104. # Do some additional inserts
  105. #
  106. do_test btree-3.1 {
  107. btree_begin_transaction $::b1
  108. btree_insert $::c1 two 2.00
  109. btree_key $::c1
  110. } {two}
  111. do_test btree-3.1.1 {
  112. lindex [btree_pager_stats $::b1] 1
  113. } {2}
  114. do_test btree-3.2 {
  115. btree_insert $::c1 three 3.00
  116. btree_key $::c1
  117. } {three}
  118. do_test btree-3.4 {
  119. btree_insert $::c1 four 4.00
  120. btree_key $::c1
  121. } {four}
  122. do_test btree-3.5 {
  123. btree_insert $::c1 five 5.00
  124. btree_key $::c1
  125. } {five}
  126. do_test btree-3.6 {
  127. btree_insert $::c1 six 6.00
  128. btree_key $::c1
  129. } {six}
  130. #btree_page_dump $::b1 2
  131. do_test btree-3.7 {
  132. set rc [btree_move_to $::c1 {}]
  133. expr {$rc>0}
  134. } {1}
  135. do_test btree-3.8 {
  136. btree_key $::c1
  137. } {five}
  138. do_test btree-3.9 {
  139. btree_data $::c1
  140. } {5.00}
  141. do_test btree-3.10 {
  142. btree_next $::c1
  143. btree_key $::c1
  144. } {four}
  145. do_test btree-3.11 {
  146. btree_data $::c1
  147. } {4.00}
  148. do_test btree-3.12 {
  149. btree_next $::c1
  150. btree_key $::c1
  151. } {one}
  152. do_test btree-3.13 {
  153. btree_data $::c1
  154. } {1.00}
  155. do_test btree-3.14 {
  156. btree_next $::c1
  157. btree_key $::c1
  158. } {six}
  159. do_test btree-3.15 {
  160. btree_data $::c1
  161. } {6.00}
  162. do_test btree-3.16 {
  163. btree_next $::c1
  164. btree_key $::c1
  165. } {three}
  166. do_test btree-3.17 {
  167. btree_data $::c1
  168. } {3.00}
  169. do_test btree-3.18 {
  170. btree_next $::c1
  171. btree_key $::c1
  172. } {two}
  173. do_test btree-3.19 {
  174. btree_data $::c1
  175. } {2.00}
  176. do_test btree-3.20 {
  177. btree_next $::c1
  178. btree_key $::c1
  179. } {}
  180. do_test btree-3.21 {
  181. btree_data $::c1
  182. } {}
  183. # Commit the changes, reopen and reread the data
  184. #
  185. do_test btree-3.22 {
  186. set rc [catch {btree_close_cursor $::c1} msg]
  187. lappend rc $msg
  188. } {0 {}}
  189. do_test btree-3.22.1 {
  190. lindex [btree_pager_stats $::b1] 1
  191. } {1}
  192. do_test btree-3.23 {
  193. set rc [catch {btree_commit $::b1} msg]
  194. lappend rc $msg
  195. } {0 {}}
  196. do_test btree-3.23.1 {
  197. lindex [btree_pager_stats $::b1] 1
  198. } {0}
  199. do_test btree-3.24 {
  200. file size test1.bt
  201. } {2048}
  202. do_test btree-3.25 {
  203. set rc [catch {btree_cursor $::b1 2 1} ::c1]
  204. if {$rc} {lappend rc $::c1}
  205. set rc
  206. } {0}
  207. do_test btree-3.25.1 {
  208. lindex [btree_pager_stats $::b1] 1
  209. } {2}
  210. do_test btree-3.26 {
  211. set rc [btree_move_to $::c1 {}]
  212. expr {$rc>0}
  213. } {1}
  214. do_test btree-3.27 {
  215. btree_key $::c1
  216. } {five}
  217. do_test btree-3.28 {
  218. btree_data $::c1
  219. } {5.00}
  220. do_test btree-3.29 {
  221. btree_next $::c1
  222. btree_key $::c1
  223. } {four}
  224. do_test btree-3.30 {
  225. btree_data $::c1
  226. } {4.00}
  227. do_test btree-3.31 {
  228. btree_next $::c1
  229. btree_key $::c1
  230. } {one}
  231. do_test btree-3.32 {
  232. btree_data $::c1
  233. } {1.00}
  234. do_test btree-3.33 {
  235. btree_next $::c1
  236. btree_key $::c1
  237. } {six}
  238. do_test btree-3.34 {
  239. btree_data $::c1
  240. } {6.00}
  241. do_test btree-3.35 {
  242. btree_next $::c1
  243. btree_key $::c1
  244. } {three}
  245. do_test btree-3.36 {
  246. btree_data $::c1
  247. } {3.00}
  248. do_test btree-3.37 {
  249. btree_next $::c1
  250. btree_key $::c1
  251. } {two}
  252. do_test btree-3.38 {
  253. btree_data $::c1
  254. } {2.00}
  255. do_test btree-3.39 {
  256. btree_next $::c1
  257. btree_key $::c1
  258. } {}
  259. do_test btree-3.40 {
  260. btree_data $::c1
  261. } {}
  262. do_test btree-3.41 {
  263. lindex [btree_pager_stats $::b1] 1
  264. } {2}
  265. # Now try a delete
  266. #
  267. do_test btree-4.1 {
  268. btree_begin_transaction $::b1
  269. btree_move_to $::c1 one
  270. btree_key $::c1
  271. } {one}
  272. do_test btree-4.1.1 {
  273. lindex [btree_pager_stats $::b1] 1
  274. } {2}
  275. do_test btree-4.2 {
  276. btree_delete $::c1
  277. } {}
  278. do_test btree-4.3 {
  279. btree_key $::c1
  280. } {six}
  281. do_test btree-4.4 {
  282. btree_next $::c1
  283. btree_key $::c1
  284. } {six}
  285. do_test btree-4.5 {
  286. btree_next $::c1
  287. btree_key $::c1
  288. } {three}
  289. do_test btree-4.4 {
  290. btree_move_to $::c1 {}
  291. set r {}
  292. while 1 {
  293. set key [btree_key $::c1]
  294. if {$key==""} break
  295. lappend r $key
  296. lappend r [btree_data $::c1]
  297. btree_next $::c1
  298. }
  299. set r
  300. } {five 5.00 four 4.00 six 6.00 three 3.00 two 2.00}
  301. # Commit and make sure the delete is still there.
  302. #
  303. do_test btree-4.5 {
  304. btree_commit $::b1
  305. btree_move_to $::c1 {}
  306. set r {}
  307. while 1 {
  308. set key [btree_key $::c1]
  309. if {$key==""} break
  310. lappend r $key
  311. lappend r [btree_data $::c1]
  312. btree_next $::c1
  313. }
  314. set r
  315. } {five 5.00 four 4.00 six 6.00 three 3.00 two 2.00}
  316. # Completely close the database and reopen it. Then check
  317. # the data again.
  318. #
  319. do_test btree-4.6 {
  320. lindex [btree_pager_stats $::b1] 1
  321. } {2}
  322. do_test btree-4.7 {
  323. btree_close_cursor $::c1
  324. lindex [btree_pager_stats $::b1] 1
  325. } {0}
  326. do_test btree-4.8 {
  327. btree_close $::b1
  328. set ::b1 [btree_open test1.bt]
  329. set ::c1 [btree_cursor $::b1 2 1]
  330. lindex [btree_pager_stats $::b1] 1
  331. } {2}
  332. do_test btree-4.9 {
  333. set r {}
  334. while 1 {
  335. set key [btree_key $::c1]
  336. if {$key==""} break
  337. lappend r $key
  338. lappend r [btree_data $::c1]
  339. btree_next $::c1
  340. }
  341. set r
  342. } {five 5.00 four 4.00 six 6.00 three 3.00 two 2.00}
  343. # Try to read and write meta data
  344. #
  345. do_test btree-5.1 {
  346. btree_get_meta $::b1
  347. } {0 0 0 0}
  348. do_test btree-5.2 {
  349. set rc [catch {btree_update_meta $::b1 1 2 3 4} msg]
  350. lappend rc $msg
  351. } {1 SQLITE_ERROR}
  352. do_test btree-5.3 {
  353. btree_begin_transaction $::b1
  354. set rc [catch {btree_update_meta $::b1 1 2 3 4} msg]
  355. lappend rc $msg
  356. } {0 {}}
  357. do_test btree-5.4 {
  358. btree_get_meta $::b1
  359. } {0 2 3 4}
  360. do_test btree-5.5 {
  361. btree_close_cursor $::c1
  362. btree_rollback $::b1
  363. btree_get_meta $::b1
  364. } {0 0 0 0}
  365. do_test btree-5.6 {
  366. btree_begin_transaction $::b1
  367. btree_update_meta $::b1 999 10 20 30
  368. btree_commit $::b1
  369. btree_get_meta $::b1
  370. } {0 10 20 30}
  371. proc select_all {cursor} {
  372. set r {}
  373. btree_move_to $cursor {}
  374. while 1 {
  375. set key [btree_key $cursor]
  376. if {$key==""} break
  377. lappend r $key
  378. lappend r [btree_data $cursor]
  379. btree_next $cursor
  380. }
  381. return $r
  382. }
  383. proc select_keys {cursor} {
  384. set r {}
  385. btree_move_to $cursor {}
  386. while 1 {
  387. set key [btree_key $cursor]
  388. if {$key==""} break
  389. lappend r $key
  390. btree_next $cursor
  391. }
  392. return $r
  393. }
  394. # Try to create a new table in the database file
  395. #
  396. do_test btree-6.1 {
  397. set rc [catch {btree_create_table $::b1} msg]
  398. lappend rc $msg
  399. } {1 SQLITE_ERROR}
  400. do_test btree-6.2 {
  401. btree_begin_transaction $::b1
  402. set ::t2 [btree_create_table $::b1]
  403. } {3}
  404. do_test btree-6.2.1 {
  405. lindex [btree_pager_stats $::b1] 1
  406. } {1}
  407. do_test btree-6.2.2 {
  408. set ::c2 [btree_cursor $::b1 $::t2 1]
  409. lindex [btree_pager_stats $::b1] 1
  410. } {2}
  411. do_test btree-6.2.3 {
  412. btree_insert $::c2 ten 10
  413. btree_key $::c2
  414. } {ten}
  415. do_test btree-6.3 {
  416. btree_commit $::b1
  417. set ::c1 [btree_cursor $::b1 2 1]
  418. lindex [btree_pager_stats $::b1] 1
  419. } {3}
  420. do_test btree-6.3.1 {
  421. select_all $::c1
  422. } {five 5.00 four 4.00 six 6.00 three 3.00 two 2.00}
  423. #btree_page_dump $::b1 3
  424. do_test btree-6.4 {
  425. select_all $::c2
  426. } {ten 10}
  427. # Drop the new table, then create it again anew.
  428. #
  429. do_test btree-6.5 {
  430. btree_begin_transaction $::b1
  431. } {}
  432. do_test btree-6.6 {
  433. btree_close_cursor $::c2
  434. } {}
  435. do_test btree-6.6.1 {
  436. lindex [btree_pager_stats $::b1] 1
  437. } {2}
  438. do_test btree-6.7 {
  439. btree_drop_table $::b1 $::t2
  440. } {}
  441. do_test btree-6.7.1 {
  442. lindex [btree_get_meta $::b1] 0
  443. } {1}
  444. do_test btree-6.8 {
  445. set ::t2 [btree_create_table $::b1]
  446. } {3}
  447. do_test btree-6.8.1 {
  448. lindex [btree_get_meta $::b1] 0
  449. } {0}
  450. do_test btree-6.9 {
  451. set ::c2 [btree_cursor $::b1 $::t2 1]
  452. lindex [btree_pager_stats $::b1] 1
  453. } {3}
  454. do_test btree-6.9.1 {
  455. btree_move_to $::c2 {}
  456. btree_key $::c2
  457. } {}
  458. # If we drop table 2 it just clears the table. Table 2 always exists.
  459. #
  460. do_test btree-6.10 {
  461. btree_close_cursor $::c1
  462. btree_drop_table $::b1 2
  463. set ::c1 [btree_cursor $::b1 2 1]
  464. btree_move_to $::c1 {}
  465. btree_key $::c1
  466. } {}
  467. do_test btree-6.11 {
  468. btree_commit $::b1
  469. select_all $::c1
  470. } {}
  471. do_test btree-6.12 {
  472. select_all $::c2
  473. } {}
  474. do_test btree-6.13 {
  475. btree_close_cursor $::c2
  476. lindex [btree_pager_stats $::b1] 1
  477. } {2}
  478. # Check to see that pages defragment properly. To do this test we will
  479. #
  480. # 1. Fill the first page table 2 with data.
  481. # 2. Delete every other entry of table 2.
  482. # 3. Insert a single entry that requires more contiguous
  483. # space than is available.
  484. #
  485. do_test btree-7.1 {
  486. btree_begin_transaction $::b1
  487. } {}
  488. catch {unset key}
  489. catch {unset data}
  490. do_test btree-7.2 {
  491. for {set i 0} {$i<36} {incr i} {
  492. set key [format %03d $i]
  493. set data "*** $key ***"
  494. btree_insert $::c1 $key $data
  495. }
  496. lrange [btree_cursor_dump $::c1] 4 5
  497. } {8 1}
  498. do_test btree-7.3 {
  499. btree_move_to $::c1 000
  500. while {[btree_key $::c1]!=""} {
  501. btree_delete $::c1
  502. btree_next $::c1
  503. btree_next $::c1
  504. }
  505. lrange [btree_cursor_dump $::c1] 4 5
  506. } {512 19}
  507. #btree_page_dump $::b1 2
  508. do_test btree-7.4 {
  509. btree_insert $::c1 018 {*** 018 ***+++}
  510. btree_key $::c1
  511. } {018}
  512. do_test btree-7.5 {
  513. lrange [btree_cursor_dump $::c1] 4 5
  514. } {480 1}
  515. #btree_page_dump $::b1 2
  516. # Delete an entry to make a hole of a known size, then immediately recreate
  517. # that entry. This tests the path into allocateSpace where the hole exactly
  518. # matches the size of the desired space.
  519. #
  520. do_test btree-7.6 {
  521. btree_move_to $::c1 007
  522. btree_delete $::c1
  523. btree_move_to $::c1 011
  524. btree_delete $::c1
  525. } {}
  526. do_test btree-7.7 {
  527. lindex [btree_cursor_dump $::c1] 5
  528. } {3}
  529. #btree_page_dump $::b1 2
  530. do_test btree-7.8 {
  531. btree_insert $::c1 007 {*** 007 ***}
  532. lindex [btree_cursor_dump $::c1] 5
  533. } {2}
  534. #btree_page_dump $::b1 2
  535. # Make sure the freeSpace() routine properly coaleses adjacent memory blocks
  536. #
  537. do_test btree-7.9 {
  538. btree_move_to $::c1 013
  539. btree_delete $::c1
  540. lrange [btree_cursor_dump $::c1] 4 5
  541. } {536 2}
  542. do_test btree-7.10 {
  543. btree_move_to $::c1 009
  544. btree_delete $::c1
  545. lrange [btree_cursor_dump $::c1] 4 5
  546. } {564 2}
  547. do_test btree-7.11 {
  548. btree_move_to $::c1 018
  549. btree_delete $::c1
  550. lrange [btree_cursor_dump $::c1] 4 5
  551. } {596 2}
  552. do_test btree-7.13 {
  553. btree_move_to $::c1 033
  554. btree_delete $::c1
  555. lrange [btree_cursor_dump $::c1] 4 5
  556. } {624 3}
  557. do_test btree-7.14 {
  558. btree_move_to $::c1 035
  559. btree_delete $::c1
  560. lrange [btree_cursor_dump $::c1] 4 5
  561. } {652 2}
  562. #btree_page_dump $::b1 2
  563. do_test btree-7.15 {
  564. lindex [btree_pager_stats $::b1] 1
  565. } {2}
  566. # Check to see that data on overflow pages work correctly.
  567. #
  568. do_test btree-8.1 {
  569. set data "*** This is a very long key "
  570. while {[string length $data]<256} {append data $data}
  571. set ::data $data
  572. btree_insert $::c1 020 $data
  573. } {}
  574. #btree_page_dump $::b1 2
  575. do_test btree-8.1.1 {
  576. lindex [btree_pager_stats $::b1] 1
  577. } {2}
  578. #btree_pager_ref_dump $::b1
  579. do_test btree-8.2 {
  580. string length [btree_data $::c1]
  581. } [string length $::data]
  582. do_test btree-8.3 {
  583. btree_data $::c1
  584. } $::data
  585. do_test btree-8.4 {
  586. btree_delete $::c1
  587. } {}
  588. do_test btree-8.4.1 {
  589. lindex [btree_get_meta $::b1] 0
  590. } [expr {int(([string length $::data]-238+1019)/1020)}]
  591. do_test btree-8.5 {
  592. set data "*** This is an even longer key"
  593. while {[string length $data]<2000} {append data $data}
  594. set ::data $data
  595. btree_insert $::c1 020 $data
  596. } {}
  597. do_test btree-8.6 {
  598. string length [btree_data $::c1]
  599. } [string length $::data]
  600. do_test btree-8.7 {
  601. btree_data $::c1
  602. } $::data
  603. do_test btree-8.8 {
  604. btree_commit $::b1
  605. btree_data $::c1
  606. } $::data
  607. do_test btree-8.9 {
  608. btree_close_cursor $::c1
  609. btree_close $::b1
  610. set ::b1 [btree_open test1.bt]
  611. set ::c1 [btree_cursor $::b1 2 1]
  612. btree_move_to $::c1 020
  613. btree_data $::c1
  614. } $::data
  615. do_test btree-8.10 {
  616. btree_begin_transaction $::b1
  617. btree_delete $::c1
  618. } {}
  619. do_test btree-8.11 {
  620. lindex [btree_get_meta $::b1] 0
  621. } [expr {int(([string length $::data]-238+1019)/1020)}]
  622. # Now check out keys on overflow pages.
  623. #
  624. do_test btree-8.12 {
  625. set ::keyprefix "This is a long prefix to a key "
  626. while {[string length $::keyprefix]<256} {append ::keyprefix $::keyprefix}
  627. btree_close_cursor $::c1
  628. btree_drop_table $::b1 2
  629. lindex [btree_get_meta $::b1] 0
  630. } {4}
  631. do_test btree-8.12.1 {
  632. set ::c1 [btree_cursor $::b1 2 1]
  633. btree_insert $::c1 ${::keyprefix}1 1
  634. btree_data $::c1
  635. } {1}
  636. do_test btree-8.13 {
  637. btree_key $::c1
  638. } ${keyprefix}1
  639. do_test btree-8.14 {
  640. btree_insert $::c1 ${::keyprefix}2 2
  641. btree_insert $::c1 ${::keyprefix}3 3
  642. btree_key $::c1
  643. } ${keyprefix}3
  644. do_test btree-8.15 {
  645. btree_move_to $::c1 ${::keyprefix}2
  646. btree_data $::c1
  647. } {2}
  648. do_test btree-8.16 {
  649. btree_move_to $::c1 ${::keyprefix}1
  650. btree_data $::c1
  651. } {1}
  652. do_test btree-8.17 {
  653. btree_move_to $::c1 ${::keyprefix}3
  654. btree_data $::c1
  655. } {3}
  656. do_test btree-8.18 {
  657. lindex [btree_get_meta $::b1] 0
  658. } {1}
  659. do_test btree-8.19 {
  660. btree_move_to $::c1 ${::keyprefix}2
  661. btree_key $::c1
  662. } ${::keyprefix}2
  663. #btree_page_dump $::b1 2
  664. do_test btree-8.20 {
  665. btree_delete $::c1
  666. btree_next $::c1
  667. btree_key $::c1
  668. } ${::keyprefix}3
  669. #btree_page_dump $::b1 2
  670. do_test btree-8.21 {
  671. lindex [btree_get_meta $::b1] 0
  672. } {2}
  673. do_test btree-8.22 {
  674. lindex [btree_pager_stats $::b1] 1
  675. } {2}
  676. do_test btree-8.23 {
  677. btree_close_cursor $::c1
  678. btree_drop_table $::b1 2
  679. set ::c1 [btree_cursor $::b1 2 1]
  680. lindex [btree_get_meta $::b1] 0
  681. } {4}
  682. do_test btree-8.24 {
  683. lindex [btree_pager_stats $::b1] 1
  684. } {2}
  685. #btree_pager_ref_dump $::b1
  686. # Check page splitting logic
  687. #
  688. do_test btree-9.1 {
  689. for {set i 1} {$i<=19} {incr i} {
  690. set key [format %03d $i]
  691. set data "*** $key *** $key *** $key *** $key ***"
  692. btree_insert $::c1 $key $data
  693. }
  694. } {}
  695. #btree_tree_dump $::b1 2
  696. #btree_pager_ref_dump $::b1
  697. #set pager_refinfo_enable 1
  698. do_test btree-9.2 {
  699. btree_insert $::c1 020 {*** 020 *** 020 *** 020 *** 020 ***}
  700. select_keys $::c1
  701. } {001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020}
  702. #btree_page_dump $::b1 5
  703. #btree_page_dump $::b1 2
  704. #btree_page_dump $::b1 7
  705. #btree_pager_ref_dump $::b1
  706. #set pager_refinfo_enable 0
  707. # The previous "select_keys" command left the cursor pointing at the root
  708. # page. So there should only be two pages checked out. 2 (the root) and
  709. # page 1.
  710. do_test btree-9.2.1 {
  711. lindex [btree_pager_stats $::b1] 1
  712. } {2}
  713. for {set i 1} {$i<=20} {incr i} {
  714. do_test btree-9.3.$i.1 [subst {
  715. btree_move_to $::c1 [format %03d $i]
  716. btree_key $::c1
  717. }] [format %03d $i]
  718. do_test btree-9.3.$i.2 [subst {
  719. btree_move_to $::c1 [format %03d $i]
  720. string range \[btree_data $::c1\] 0 10
  721. }] "*** [format %03d $i] ***"
  722. }
  723. do_test btree-9.4.1 {
  724. lindex [btree_pager_stats $::b1] 1
  725. } {3}
  726. # Check the page joining logic.
  727. #
  728. #btree_page_dump $::b1 2
  729. #btree_pager_ref_dump $::b1
  730. do_test btree-9.4.2 {
  731. btree_move_to $::c1 005
  732. btree_delete $::c1
  733. } {}
  734. #btree_page_dump $::b1 2
  735. for {set i 1} {$i<=19} {incr i} {
  736. if {$i==5} continue
  737. do_test btree-9.5.$i.1 [subst {
  738. btree_move_to $::c1 [format %03d $i]
  739. btree_key $::c1
  740. }] [format %03d $i]
  741. do_test btree-9.5.$i.2 [subst {
  742. btree_move_to $::c1 [format %03d $i]
  743. string range \[btree_data $::c1\] 0 10
  744. }] "*** [format %03d $i] ***"
  745. }
  746. #btree_pager_ref_dump $::b1
  747. do_test btree-9.6 {
  748. btree_close_cursor $::c1
  749. lindex [btree_pager_stats $::b1] 1
  750. } {1}
  751. do_test btree-9.7 {
  752. btree_rollback $::b1
  753. lindex [btree_pager_stats $::b1] 1
  754. } {0}
  755. # Create a tree of depth two. That is, there is a single divider entry
  756. # on the root pages and two leaf pages. Then delete the divider entry
  757. # see what happens.
  758. #
  759. do_test btree-10.1 {
  760. btree_begin_transaction $::b1
  761. btree_drop_table $::b1 2
  762. lindex [btree_pager_stats $::b1] 1
  763. } {1}
  764. do_test btree-10.2 {
  765. set ::c1 [btree_cursor $::b1 2 1]
  766. lindex [btree_pager_stats $::b1] 1
  767. } {2}
  768. do_test btree-10.3 {
  769. for {set i 1} {$i<=20} {incr i} {
  770. set key [format %03d $i]
  771. set data "*** $key *** $key *** $key *** $key ***"
  772. btree_insert $::c1 $key $data
  773. }
  774. select_keys $::c1
  775. } {001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020}
  776. #btree_page_dump $::b1 7
  777. #btree_page_dump $::b1 2
  778. #btree_page_dump $::b1 6
  779. do_test btree-10.4 {
  780. btree_move_to $::c1 011
  781. btree_delete $::c1
  782. select_keys $::c1
  783. } {001 002 003 004 005 006 007 008 009 010 012 013 014 015 016 017 018 019 020}
  784. #btree_tree_dump $::b1 2
  785. #btree_pager_ref_dump $::b1
  786. for {set i 1} {$i<=20} {incr i} {
  787. do_test btree-10.5.$i {
  788. btree_move_to $::c1 [format %03d $i]
  789. lindex [btree_pager_stats $::b1] 1
  790. } {2}
  791. #btree_pager_ref_dump $::b1
  792. #btree_tree_dump $::b1 2
  793. }
  794. # Create a tree with lots more pages
  795. #
  796. catch {unset ::data}
  797. catch {unset ::key}
  798. for {set i 21} {$i<=1000} {incr i} {
  799. do_test btree-11.1.$i.1 {
  800. set key [format %03d $i]
  801. set ::data "*** $key *** $key *** $key *** $key ***"
  802. btree_insert $::c1 $key $data
  803. btree_key $::c1
  804. } [format %03d $i]
  805. do_test btree-11.1.$i.2 {
  806. btree_data $::c1
  807. } $::data
  808. set ::key [format %03d [expr {$i/2}]]
  809. if {$::key=="011"} {set ::key 010}
  810. do_test btree-11.1.$i.3 {
  811. btree_move_to $::c1 $::key
  812. btree_key $::c1
  813. } $::key
  814. }
  815. catch {unset ::data}
  816. catch {unset ::key}
  817. # Make sure our reference count is still correct.
  818. #
  819. do_test btree-11.2 {
  820. btree_close_cursor $::c1
  821. lindex [btree_pager_stats $::b1] 1
  822. } {1}
  823. do_test btree-11.3 {
  824. set ::c1 [btree_cursor $::b1 2 1]
  825. lindex [btree_pager_stats $::b1] 1
  826. } {2}
  827. #btree_page_dump $::b1 2
  828. # Delete the dividers on the root page
  829. #
  830. do_test btree-11.4 {
  831. btree_move_to $::c1 257
  832. btree_delete $::c1
  833. btree_next $::c1
  834. btree_key $::c1
  835. } {258}
  836. do_test btree-11.4.1 {
  837. btree_move_to $::c1 256
  838. btree_key $::c1
  839. } {256}
  840. do_test btree-11.4.2 {
  841. btree_move_to $::c1 258
  842. btree_key $::c1
  843. } {258}
  844. do_test btree-11.4.3 {
  845. btree_move_to $::c1 259
  846. btree_key $::c1
  847. } {259}
  848. do_test btree-11.4.4 {
  849. btree_move_to $::c1 257
  850. set n [btree_key $::c1]
  851. expr {$n==256||$n==258}
  852. } {1}
  853. do_test btree-11.5 {
  854. btree_move_to $::c1 513
  855. btree_delete $::c1
  856. btree_next $::c1
  857. btree_key $::c1
  858. } {514}
  859. do_test btree-11.5.1 {
  860. btree_move_to $::c1 512
  861. btree_key $::c1
  862. } {512}
  863. do_test btree-11.5.2 {
  864. btree_move_to $::c1 514
  865. btree_key $::c1
  866. } {514}
  867. do_test btree-11.5.3 {
  868. btree_move_to $::c1 515
  869. btree_key $::c1
  870. } {515}
  871. do_test btree-11.5.4 {
  872. btree_move_to $::c1 513
  873. set n [btree_key $::c1]
  874. expr {$n==512||$n==514}
  875. } {1}
  876. do_test btree-11.6 {
  877. btree_move_to $::c1 769
  878. btree_delete $::c1
  879. btree_next $::c1
  880. btree_key $::c1
  881. } {770}
  882. do_test btree-11.6.1 {
  883. btree_move_to $::c1 768
  884. btree_key $::c1
  885. } {768}
  886. do_test btree-11.6.2 {
  887. btree_move_to $::c1 771
  888. btree_key $::c1
  889. } {771}
  890. do_test btree-11.6.3 {
  891. btree_move_to $::c1 770
  892. btree_key $::c1
  893. } {770}
  894. do_test btree-11.6.4 {
  895. btree_move_to $::c1 769
  896. set n [btree_key $::c1]
  897. expr {$n==768||$n==770}
  898. } {1}
  899. #btree_page_dump $::b1 2
  900. #btree_page_dump $::b1 25
  901. # Change the data on an intermediate node such that the node becomes overfull
  902. # and has to split. We happen to know that intermediate nodes exist on
  903. # 337, 401 and 465 by the btree_page_dumps above
  904. #
  905. catch {unset ::data}
  906. set ::data {This is going to be a very long data segment}
  907. append ::data $::data
  908. append ::data $::data
  909. do_test btree-12.1 {
  910. btree_insert $::c1 337 $::data
  911. btree_data $::c1
  912. } $::data
  913. do_test btree-12.2 {
  914. btree_insert $::c1 401 $::data
  915. btree_data $::c1
  916. } $::data
  917. do_test btree-12.3 {
  918. btree_insert $::c1 465 $::data
  919. btree_data $::c1
  920. } $::data
  921. do_test btree-12.4 {
  922. btree_move_to $::c1 337
  923. btree_key $::c1
  924. } {337}
  925. do_test btree-12.5 {
  926. btree_data $::c1
  927. } $::data
  928. do_test btree-12.6 {
  929. btree_next $::c1
  930. btree_key $::c1
  931. } {338}
  932. do_test btree-12.7 {
  933. btree_move_to $::c1 464
  934. btree_key $::c1
  935. } {464}
  936. do_test btree-12.8 {
  937. btree_next $::c1
  938. btree_data $::c1
  939. } $::data
  940. do_test btree-12.9 {
  941. btree_next $::c1
  942. btree_key $::c1
  943. } {466}
  944. do_test btree-12.10 {
  945. btree_move_to $::c1 400
  946. btree_key $::c1
  947. } {400}
  948. do_test btree-12.11 {
  949. btree_next $::c1
  950. btree_data $::c1
  951. } $::data
  952. do_test btree-12.12 {
  953. btree_next $::c1
  954. btree_key $::c1
  955. } {402}
  956. do_test btree-13.1 {
  957. btree_integrity_check $::b1 2 3
  958. } {}
  959. # To Do:
  960. #
  961. # 1. Do some deletes from the 3-layer tree
  962. # 2. Commit and reopen the database
  963. # 3. Read every 15th entry and make sure it works
  964. # 4. Implement btree_sanity and put it throughout this script
  965. #
  966. do_test btree-15.98 {
  967. btree_close_cursor $::c1
  968. lindex [btree_pager_stats $::b1] 1
  969. } {1}
  970. do_test btree-15.99 {
  971. btree_rollback $::b1
  972. lindex [btree_pager_stats $::b1] 1
  973. } {0}
  974. btree_pager_ref_dump $::b1
  975. do_test btree-99.1 {
  976. btree_close $::b1
  977. } {}
  978. catch {unset data}
  979. catch {unset key}
  980. } ;# end if( not mem: and has pager_open command );
  981. finish_test