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