OLD | NEW |
1 # 2007 May 1 | 1 # 2007 May 1 |
2 # | 2 # |
3 # The author disclaims copyright to this source code. In place of | 3 # The author disclaims copyright to this source code. In place of |
4 # a legal notice, here is a blessing: | 4 # a legal notice, here is a blessing: |
5 # | 5 # |
6 # May you do good and not evil. | 6 # May you do good and not evil. |
7 # May you find forgiveness for yourself and forgive others. | 7 # May you find forgiveness for yourself and forgive others. |
8 # May you share freely, never taking more than you give. | 8 # May you share freely, never taking more than you give. |
9 # | 9 # |
10 #*********************************************************************** | 10 #*********************************************************************** |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
113 | 113 |
114 foreach AutoVacuumMode [list 0 1] { | 114 foreach AutoVacuumMode [list 0 1] { |
115 | 115 |
116 if {$AutoVacuumMode>0} { | 116 if {$AutoVacuumMode>0} { |
117 ifcapable !autovacuum { | 117 ifcapable !autovacuum { |
118 break | 118 break |
119 } | 119 } |
120 } | 120 } |
121 | 121 |
122 db close | 122 db close |
123 file delete -force test.db test.db-journal | 123 forcedelete test.db test.db-journal |
124 | 124 |
125 sqlite3 db test.db | 125 sqlite3 db test.db |
| 126 execsql "PRAGMA mmap_size = 0" |
126 execsql "PRAGMA auto_vacuum = $AutoVacuumMode" | 127 execsql "PRAGMA auto_vacuum = $AutoVacuumMode" |
127 | 128 |
128 do_test incrblob-2.$AutoVacuumMode.1 { | 129 do_test incrblob-2.$AutoVacuumMode.1 { |
129 set ::str [string repeat abcdefghij 2900] | 130 set ::str [string repeat abcdefghij 2900] |
130 execsql { | 131 execsql { |
131 BEGIN; | 132 BEGIN; |
132 CREATE TABLE blobs(k PRIMARY KEY, v BLOB, i INTEGER); | 133 CREATE TABLE blobs(k PRIMARY KEY, v BLOB, i INTEGER); |
133 DELETE FROM blobs; | 134 DELETE FROM blobs; |
134 INSERT INTO blobs VALUES('one', $::str || randstr(500,500), 45); | 135 INSERT INTO blobs VALUES('one', $::str || randstr(500,500), 45); |
135 COMMIT; | 136 COMMIT; |
136 } | 137 } |
137 expr [file size test.db]/1024 | 138 expr [file size test.db]/1024 |
138 } [expr 31 + $AutoVacuumMode] | 139 } [expr 31 + $AutoVacuumMode] |
139 | 140 |
140 ifcapable autovacuum { | 141 ifcapable autovacuum { |
141 do_test incrblob-2.$AutoVacuumMode.2 { | 142 do_test incrblob-2.$AutoVacuumMode.2 { |
142 execsql { | 143 execsql { |
143 PRAGMA auto_vacuum; | 144 PRAGMA auto_vacuum; |
144 } | 145 } |
145 } $AutoVacuumMode | 146 } $AutoVacuumMode |
146 } | 147 } |
147 | 148 |
148 do_test incrblob-2.$AutoVacuumMode.3 { | 149 do_test incrblob-2.$AutoVacuumMode.3 { |
149 # Open and close the db to make sure the page cache is empty. | 150 # Open and close the db to make sure the page cache is empty. |
150 db close | 151 db close |
151 sqlite3 db test.db | 152 sqlite3 db test.db |
| 153 execsql "PRAGMA mmap_size = 0" |
152 | 154 |
153 # Read the last 20 bytes of the blob via a blob handle. | 155 # Read the last 20 bytes of the blob via a blob handle. |
154 set ::blob [db incrblob blobs v 1] | 156 set ::blob [db incrblob blobs v 1] |
155 seek $::blob -20 end | 157 seek $::blob -20 end |
156 set ::fragment [read $::blob] | 158 set ::fragment [read $::blob] |
157 close $::blob | 159 close $::blob |
158 | 160 |
159 # If the database is not in auto-vacuum mode, the whole of | 161 # If the database is not in auto-vacuum mode, the whole of |
160 # the overflow-chain must be scanned. In auto-vacuum mode, | 162 # the overflow-chain must be scanned. In auto-vacuum mode, |
161 # sqlite uses the ptrmap pages to avoid reading the other pages. | 163 # sqlite uses the ptrmap pages to avoid reading the other pages. |
162 # | 164 # |
163 nRead db | 165 nRead db |
164 } [expr $AutoVacuumMode ? 4 : 30] | 166 } [expr $AutoVacuumMode ? 4 : 30] |
165 | 167 |
166 do_test incrblob-2.$AutoVacuumMode.4 { | 168 do_test incrblob-2.$AutoVacuumMode.4 { |
167 string range [db one {SELECT v FROM blobs}] end-19 end | 169 string range [db one {SELECT v FROM blobs}] end-19 end |
168 } $::fragment | 170 } $::fragment |
169 | 171 |
170 do_test incrblob-2.$AutoVacuumMode.5 { | 172 do_test incrblob-2.$AutoVacuumMode.5 { |
171 # Open and close the db to make sure the page cache is empty. | 173 # Open and close the db to make sure the page cache is empty. |
172 db close | 174 db close |
173 sqlite3 db test.db | 175 sqlite3 db test.db |
| 176 execsql "PRAGMA mmap_size = 0" |
174 | 177 |
175 # Write the second-to-last 20 bytes of the blob via a blob handle. | 178 # Write the second-to-last 20 bytes of the blob via a blob handle. |
176 # | 179 # |
177 set ::blob [db incrblob blobs v 1] | 180 set ::blob [db incrblob blobs v 1] |
178 seek $::blob -40 end | 181 seek $::blob -40 end |
179 puts -nonewline $::blob "1234567890abcdefghij" | 182 puts -nonewline $::blob "1234567890abcdefghij" |
180 flush $::blob | 183 flush $::blob |
181 | 184 |
182 # If the database is not in auto-vacuum mode, the whole of | 185 # If the database is not in auto-vacuum mode, the whole of |
183 # the overflow-chain must be scanned. In auto-vacuum mode, | 186 # the overflow-chain must be scanned. In auto-vacuum mode, |
184 # sqlite uses the ptrmap pages to avoid reading the other pages. | 187 # sqlite uses the ptrmap pages to avoid reading the other pages. |
185 # | 188 # |
186 nRead db | 189 nRead db |
187 } [expr $AutoVacuumMode ? 4 : 30] | 190 } [expr $AutoVacuumMode ? 4 : 30] |
188 | 191 |
189 # Pages 1 (the write-counter) and 32 (the blob data) were written. | 192 # Pages 1 (the write-counter) and 32 (the blob data) were written. |
190 do_test incrblob-2.$AutoVacuumMode.6 { | 193 do_test incrblob-2.$AutoVacuumMode.6 { |
191 close $::blob | 194 close $::blob |
192 nWrite db | 195 nWrite db |
193 } 2 | 196 } 2 |
194 | 197 |
195 do_test incrblob-2.$AutoVacuumMode.7 { | 198 do_test incrblob-2.$AutoVacuumMode.7 { |
196 string range [db one {SELECT v FROM blobs}] end-39 end-20 | 199 string range [db one {SELECT v FROM blobs}] end-39 end-20 |
197 } "1234567890abcdefghij" | 200 } "1234567890abcdefghij" |
198 | 201 |
199 do_test incrblob-2.$AutoVacuumMode.8 { | 202 do_test incrblob-2.$AutoVacuumMode.8 { |
200 # Open and close the db to make sure the page cache is empty. | 203 # Open and close the db to make sure the page cache is empty. |
201 db close | 204 db close |
202 sqlite3 db test.db | 205 sqlite3 db test.db |
| 206 execsql { PRAGMA mmap_size = 0 } |
203 | 207 |
204 execsql { SELECT i FROM blobs } | 208 execsql { SELECT i FROM blobs } |
205 } {45} | 209 } {45} |
206 | 210 |
207 do_test incrblob-2.$AutoVacuumMode.9 { | 211 do_test incrblob-2.$AutoVacuumMode.9 { |
208 nRead db | 212 nRead db |
209 } [expr $AutoVacuumMode ? 4 : 30] | 213 } [expr $AutoVacuumMode ? 4 : 30] |
210 } | 214 } |
211 sqlite3_soft_heap_limit $cmdlinearg(soft-heap-limit) | 215 sqlite3_soft_heap_limit $cmdlinearg(soft-heap-limit) |
212 | 216 |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
372 } | 376 } |
373 | 377 |
374 | 378 |
375 #------------------------------------------------------------------------ | 379 #------------------------------------------------------------------------ |
376 # incrblob-5.*: | 380 # incrblob-5.*: |
377 # | 381 # |
378 # Test that opening a blob in an attached database works. | 382 # Test that opening a blob in an attached database works. |
379 # | 383 # |
380 ifcapable attach { | 384 ifcapable attach { |
381 do_test incrblob-5.1 { | 385 do_test incrblob-5.1 { |
382 file delete -force test2.db test2.db-journal | 386 forcedelete test2.db test2.db-journal |
383 set ::size [expr [file size [info script]]] | 387 set ::size [expr [file size [info script]]] |
384 execsql { | 388 execsql { |
385 ATTACH 'test2.db' AS aux; | 389 ATTACH 'test2.db' AS aux; |
386 CREATE TABLE aux.files(name, text); | 390 CREATE TABLE aux.files(name, text); |
387 INSERT INTO aux.files VALUES('this one', zeroblob($::size)); | 391 INSERT INTO aux.files VALUES('this one', zeroblob($::size)); |
388 } | 392 } |
389 set fd [db incrblob aux files text 1] | 393 set fd [db incrblob aux files text 1] |
390 fconfigure $fd -translation binary | 394 fconfigure $fd -translation binary |
391 set fd2 [open [info script]] | 395 set fd2 [open [info script]] |
392 fconfigure $fd2 -translation binary | 396 fconfigure $fd2 -translation binary |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
430 if {[permutation] != "memsubsys1"} { | 434 if {[permutation] != "memsubsys1"} { |
431 do_test incrblob-6.1 { | 435 do_test incrblob-6.1 { |
432 sqlite3 db2 test.db | 436 sqlite3 db2 test.db |
433 execsql { | 437 execsql { |
434 BEGIN; | 438 BEGIN; |
435 INSERT INTO blobs(k, v, i) VALUES('a', 'different', 'connection'); | 439 INSERT INTO blobs(k, v, i) VALUES('a', 'different', 'connection'); |
436 } db2 | 440 } db2 |
437 } {} | 441 } {} |
438 do_test incrblob-6.2 { | 442 do_test incrblob-6.2 { |
439 execsql { | 443 execsql { |
440 SELECT rowid FROM blobs | 444 SELECT rowid FROM blobs ORDER BY rowid |
441 } | 445 } |
442 } {1 2 3} | 446 } {1 2 3} |
443 do_test incrblob-6.3 { | 447 do_test incrblob-6.3 { |
444 set rc [catch { | 448 set rc [catch { |
445 db incrblob blobs v 1 | 449 db incrblob blobs v 1 |
446 } msg] | 450 } msg] |
447 list $rc $msg | 451 list $rc $msg |
448 } {1 {database is locked}} | 452 } {1 {database is locked}} |
449 do_test incrblob-6.4 { | 453 do_test incrblob-6.4 { |
450 set rc [catch { | 454 set rc [catch { |
(...skipping 15 matching lines...) Expand all Loading... |
466 } {connection} | 470 } {connection} |
467 do_test incrblob-6.8 { | 471 do_test incrblob-6.8 { |
468 tell $::blob | 472 tell $::blob |
469 } {10} | 473 } {10} |
470 do_test incrblob-6.9 { | 474 do_test incrblob-6.9 { |
471 seek $::blob 0 | 475 seek $::blob 0 |
472 puts -nonewline $::blob "invocation" | 476 puts -nonewline $::blob "invocation" |
473 flush $::blob | 477 flush $::blob |
474 } {} | 478 } {} |
475 | 479 |
476 # At this point rollback should be illegal (because | 480 # At this point commit should be illegal (because |
477 # there is an open blob channel). But commit is also illegal because | 481 # there is an open blob channel). |
478 # the open blob is read-write. | |
479 # | 482 # |
480 do_test incrblob-6.10 { | |
481 catchsql { | |
482 ROLLBACK; | |
483 } db2 | |
484 } {1 {cannot rollback transaction - SQL statements in progress}} | |
485 do_test incrblob-6.11 { | 483 do_test incrblob-6.11 { |
486 catchsql { | 484 catchsql { |
487 COMMIT; | 485 COMMIT; |
488 } db2 | 486 } db2 |
489 } {1 {cannot commit transaction - SQL statements in progress}} | 487 } {1 {cannot commit transaction - SQL statements in progress}} |
490 | 488 |
491 do_test incrblob-6.12 { | 489 do_test incrblob-6.12 { |
492 execsql { | 490 execsql { |
493 SELECT * FROM blobs WHERE rowid = 4; | 491 SELECT * FROM blobs WHERE rowid = 4; |
494 } | 492 } |
495 } {} | 493 } {} |
496 do_test incrblob-6.13 { | 494 do_test incrblob-6.13 { |
497 close $::blob | 495 close $::blob |
498 } {} | 496 } {} |
499 do_test incrblob-6.14 { | 497 do_test incrblob-6.14 { |
500 catchsql { | 498 catchsql { |
501 COMMIT; | 499 COMMIT; |
502 } db2 | 500 } db2 |
503 } {0 {}} | 501 } {0 {}} |
504 do_test incrblob-6.15 { | 502 do_test incrblob-6.15 { |
505 execsql { | 503 execsql { |
506 SELECT * FROM blobs WHERE rowid = 4; | 504 SELECT * FROM blobs WHERE rowid = 4; |
507 } | 505 } |
508 } {a different invocation} | 506 } {a different invocation} |
509 db2 close | 507 db2 close |
510 } | 508 } |
511 sqlite3_soft_heap_limit $cmdlinearg(soft-heap-limit) | 509 sqlite3_soft_heap_limit $cmdlinearg(soft-heap-limit) |
512 | 510 |
513 #----------------------------------------------------------------------- | 511 #----------------------------------------------------------------------- |
514 # The following tests verify the behaviour of the incremental IO | 512 # The following tests verify the behavior of the incremental IO |
515 # APIs in the following cases: | 513 # APIs in the following cases: |
516 # | 514 # |
517 # 7.1 A row that containing an open blob is modified. | 515 # 7.1 A row that containing an open blob is modified. |
518 # | 516 # |
519 # 7.2 A CREATE TABLE requires that an overflow page that is part | 517 # 7.2 A CREATE TABLE requires that an overflow page that is part |
520 # of an open blob is moved. | 518 # of an open blob is moved. |
521 # | 519 # |
522 # 7.3 An INCREMENTAL VACUUM moves an overflow page that is part | 520 # 7.3 An INCREMENTAL VACUUM moves an overflow page that is part |
523 # of an open blob. | 521 # of an open blob. |
524 # | 522 # |
525 # In the first case above, correct behaviour is for all subsequent | 523 # In the first case above, correct behavior is for all subsequent |
526 # read/write operations on the blob-handle to return SQLITE_ABORT. | 524 # read/write operations on the blob-handle to return SQLITE_ABORT. |
527 # More accurately, blob-handles are invalidated whenever the table | 525 # More accurately, blob-handles are invalidated whenever the table |
528 # they belong to is written to. | 526 # they belong to is written to. |
529 # | 527 # |
530 # The second two cases have no external effect. They are testing | 528 # The second two cases have no external effect. They are testing |
531 # that the internal cache of overflow page numbers is correctly | 529 # that the internal cache of overflow page numbers is correctly |
532 # invalidated. | 530 # invalidated. |
533 # | 531 # |
534 do_test incrblob-7.1.0 { | 532 do_test incrblob-7.1.0 { |
535 execsql { | 533 execsql { |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
577 } {15} | 575 } {15} |
578 | 576 |
579 } | 577 } |
580 | 578 |
581 set fd [open [info script]] | 579 set fd [open [info script]] |
582 fconfigure $fd -translation binary | 580 fconfigure $fd -translation binary |
583 set ::data [read $fd 14000] | 581 set ::data [read $fd 14000] |
584 close $fd | 582 close $fd |
585 | 583 |
586 db close | 584 db close |
587 file delete -force test.db test.db-journal | 585 forcedelete test.db test.db-journal |
588 sqlite3 db test.db | 586 sqlite3 db test.db |
589 | 587 |
590 do_test incrblob-7.2.1 { | 588 do_test incrblob-7.2.1 { |
591 execsql { | 589 execsql { |
592 PRAGMA auto_vacuum = "incremental"; | 590 PRAGMA auto_vacuum = "incremental"; |
593 CREATE TABLE t1(a INTEGER PRIMARY KEY, b); -- root@page3 | 591 CREATE TABLE t1(a INTEGER PRIMARY KEY, b); -- root@page3 |
594 INSERT INTO t1 VALUES(123, $::data); | 592 INSERT INTO t1 VALUES(123, $::data); |
595 } | 593 } |
596 set ::b [db incrblob -readonly t1 b 123] | 594 set ::b [db incrblob -readonly t1 b 123] |
597 fconfigure $::b -translation binary | 595 fconfigure $::b -translation binary |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
681 # an error message was set using a call similar to sqlite3_mprintf(zErr), | 679 # an error message was set using a call similar to sqlite3_mprintf(zErr), |
682 # where zErr is an arbitrary string. This is no good if the string contains | 680 # where zErr is an arbitrary string. This is no good if the string contains |
683 # characters that can be mistaken for printf() formatting directives. | 681 # characters that can be mistaken for printf() formatting directives. |
684 # | 682 # |
685 do_test incrblob-9.1 { | 683 do_test incrblob-9.1 { |
686 list [catch { db incrblob t1 "A tricky column name %s%s" 1 } msg] $msg | 684 list [catch { db incrblob t1 "A tricky column name %s%s" 1 } msg] $msg |
687 } {1 {no such column: "A tricky column name %s%s"}} | 685 } {1 {no such column: "A tricky column name %s%s"}} |
688 | 686 |
689 | 687 |
690 finish_test | 688 finish_test |
OLD | NEW |