Annotation of embedaddon/sqlite3/test/incrblob.test, revision 1.1.1.1

1.1       misho       1: # 2007 May 1
                      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: # $Id: incrblob.test,v 1.24 2009/06/19 22:23:42 drh Exp $
                     13: #
                     14: 
                     15: set testdir [file dirname $argv0]
                     16: source $testdir/tester.tcl
                     17: 
                     18: ifcapable {!autovacuum || !pragma || !incrblob} {
                     19:   finish_test
                     20:   return
                     21: }
                     22: 
                     23: do_test incrblob-1.1 {
                     24:   execsql {
                     25:     CREATE TABLE blobs(k PRIMARY KEY, v BLOB);
                     26:     INSERT INTO blobs VALUES('one', X'0102030405060708090A');
                     27:     INSERT INTO blobs VALUES('two', X'0A090807060504030201');
                     28:   }
                     29: } {}
                     30: 
                     31: do_test incrblob-1.2.1 {
                     32:   set ::blob [db incrblob blobs v 1]
                     33:   string match incrblob_* $::blob
                     34: } {1}
                     35: unset -nocomplain data
                     36: do_test incrblob-1.2.2 {
                     37:   binary scan [read $::blob] c* data
                     38:   set data
                     39: } {1 2 3 4 5 6 7 8 9 10}
                     40: do_test incrblob-1.2.3 {
                     41:   seek $::blob 0
                     42:   puts -nonewline $::blob "1234567890"
                     43:   flush $::blob
                     44: } {}
                     45: do_test incrblob-1.2.4 {
                     46:   seek $::blob 0
                     47:   binary scan [read $::blob] c* data
                     48:   set data
                     49: } {49 50 51 52 53 54 55 56 57 48}
                     50: do_test incrblob-1.2.5 {
                     51:   close $::blob
                     52: } {}
                     53: do_test incrblob-1.2.6 {
                     54:   execsql {
                     55:     SELECT v FROM blobs WHERE rowid = 1;
                     56:   }
                     57: } {1234567890}
                     58: 
                     59: #--------------------------------------------------------------------
                     60: # Test cases incrblob-1.3.X check that it is possible to read and write
                     61: # regions of a blob that lie on overflow pages.
                     62: #
                     63: do_test incrblob-1.3.1 {
                     64:   set ::str "[string repeat . 10000]"
                     65:   execsql {
                     66:     INSERT INTO blobs(rowid, k, v) VALUES(3, 'three', $::str);
                     67:   }
                     68: } {}
                     69: 
                     70: do_test incrblob-1.3.2 {
                     71:   set ::blob [db incrblob blobs v 3]
                     72:   seek $::blob 8500
                     73:   read $::blob 10
                     74: } {..........}
                     75: do_test incrblob-1.3.3 {
                     76:   seek $::blob 8500
                     77:   puts -nonewline $::blob 1234567890
                     78: } {}
                     79: do_test incrblob-1.3.4 {
                     80:   seek $::blob 8496
                     81:   read $::blob 10
                     82: } {....123456}
                     83: do_test incrblob-1.3.10 {
                     84:   close $::blob
                     85: } {}
                     86: 
                     87: #------------------------------------------------------------------------
                     88: # incrblob-2.*: 
                     89: #
                     90: # Test that the following operations use ptrmap pages to reduce
                     91: # unnecessary reads:
                     92: #
                     93: #     * Reading near the end of a blob,
                     94: #     * Writing near the end of a blob, and
                     95: #     * SELECT a column value that is located on an overflow page.
                     96: #
                     97: proc nRead {db} {
                     98:   set bt [btree_from_db $db]
                     99:   db_enter $db
                    100:   array set stats [btree_pager_stats $bt]
                    101:   db_leave $db
                    102:   return $stats(read)
                    103: }
                    104: proc nWrite {db} {
                    105:   set bt [btree_from_db $db]
                    106:   db_enter $db
                    107:   array set stats [btree_pager_stats $bt]
                    108:   db_leave $db
                    109:   return $stats(write)
                    110: }
                    111: 
                    112: sqlite3_soft_heap_limit 0
                    113: 
                    114: foreach AutoVacuumMode [list 0 1] {
                    115: 
                    116:   if {$AutoVacuumMode>0} {
                    117:     ifcapable !autovacuum {
                    118:       break
                    119:     }
                    120:   }
                    121: 
                    122:   db close
                    123:   forcedelete test.db test.db-journal
                    124: 
                    125:   sqlite3 db test.db
                    126:   execsql "PRAGMA auto_vacuum = $AutoVacuumMode"
                    127: 
                    128:   do_test incrblob-2.$AutoVacuumMode.1 {
                    129:     set ::str [string repeat abcdefghij 2900]
                    130:     execsql {
                    131:       BEGIN;
                    132:       CREATE TABLE blobs(k PRIMARY KEY, v BLOB, i INTEGER);
                    133:       DELETE FROM blobs;
                    134:       INSERT INTO blobs VALUES('one', $::str || randstr(500,500), 45);
                    135:       COMMIT;
                    136:     }
                    137:     expr [file size test.db]/1024
                    138:   } [expr 31 + $AutoVacuumMode]
                    139: 
                    140:   ifcapable autovacuum {
                    141:     do_test incrblob-2.$AutoVacuumMode.2 {
                    142:       execsql {
                    143:         PRAGMA auto_vacuum;
                    144:       }
                    145:     } $AutoVacuumMode
                    146:   }
                    147: 
                    148:   do_test incrblob-2.$AutoVacuumMode.3 {
                    149:     # Open and close the db to make sure the page cache is empty.
                    150:     db close
                    151:     sqlite3 db test.db
                    152:   
                    153:     # Read the last 20 bytes of the blob via a blob handle.
                    154:     set ::blob [db incrblob blobs v 1]
                    155:     seek $::blob -20 end
                    156:     set ::fragment [read $::blob]
                    157:     close $::blob
                    158:   
                    159:     # If the database is not in auto-vacuum mode, the whole of
                    160:     # the overflow-chain must be scanned. In auto-vacuum mode,
                    161:     # sqlite uses the ptrmap pages to avoid reading the other pages.
                    162:     #
                    163:     nRead db
                    164:   } [expr $AutoVacuumMode ? 4 : 30]
                    165: 
                    166:   do_test incrblob-2.$AutoVacuumMode.4 {
                    167:     string range [db one {SELECT v FROM blobs}] end-19 end
                    168:   } $::fragment
                    169: 
                    170:   do_test incrblob-2.$AutoVacuumMode.5 {
                    171:     # Open and close the db to make sure the page cache is empty.
                    172:     db close
                    173:     sqlite3 db test.db
                    174:   
                    175:     # Write the second-to-last 20 bytes of the blob via a blob handle.
                    176:     #
                    177:     set ::blob [db incrblob blobs v 1]
                    178:     seek $::blob -40 end
                    179:     puts -nonewline $::blob "1234567890abcdefghij"
                    180:     flush $::blob
                    181:   
                    182:     # If the database is not in auto-vacuum mode, the whole of
                    183:     # the overflow-chain must be scanned. In auto-vacuum mode,
                    184:     # sqlite uses the ptrmap pages to avoid reading the other pages.
                    185:     #
                    186:     nRead db
                    187:   } [expr $AutoVacuumMode ? 4 : 30]
                    188: 
                    189:   # Pages 1 (the write-counter) and 32 (the blob data) were written.
                    190:   do_test incrblob-2.$AutoVacuumMode.6 {
                    191:     close $::blob
                    192:     nWrite db
                    193:   } 2
                    194: 
                    195:   do_test incrblob-2.$AutoVacuumMode.7 {
                    196:     string range [db one {SELECT v FROM blobs}] end-39 end-20
                    197:   } "1234567890abcdefghij"
                    198: 
                    199:   do_test incrblob-2.$AutoVacuumMode.8 {
                    200:     # Open and close the db to make sure the page cache is empty.
                    201:     db close
                    202:     sqlite3 db test.db
                    203: 
                    204:     execsql { SELECT i FROM blobs } 
                    205:   } {45}
                    206: 
                    207:   do_test incrblob-2.$AutoVacuumMode.9 {
                    208:     nRead db
                    209:   } [expr $AutoVacuumMode ? 4 : 30]
                    210: }
                    211: sqlite3_soft_heap_limit $cmdlinearg(soft-heap-limit)
                    212: 
                    213: #------------------------------------------------------------------------
                    214: # incrblob-3.*: 
                    215: #
                    216: # Test the outcome of trying to write to a read-only blob handle.
                    217: #
                    218: do_test incrblob-3.1 {
                    219:   set ::blob [db incrblob -readonly blobs v 1]
                    220:   seek $::blob -40 end
                    221:   read $::blob 20
                    222: } "1234567890abcdefghij"
                    223: do_test incrblob-3.2 {
                    224:   seek $::blob 0
                    225:   set rc [catch {
                    226:     puts -nonewline $::blob "helloworld"
                    227:   } msg]
                    228:   close $::blob
                    229:   list $rc $msg
                    230: } "1 {channel \"$::blob\" wasn't opened for writing}"
                    231: 
                    232: do_test incrblob-3.3 {
                    233:   set ::blob [db incrblob -readonly blobs v 1]
                    234:   seek $::blob -40 end
                    235:   read $::blob 20
                    236: } "1234567890abcdefghij"
                    237: do_test incrblob-3.4 {
                    238:   set rc [catch {
                    239:     sqlite3_blob_write $::blob 20 "qwertyuioplkjhgfds" 
                    240:   } msg]
                    241:   list $rc $msg
                    242: } {1 SQLITE_READONLY}
                    243: catch {close $::blob}
                    244: 
                    245: #------------------------------------------------------------------------
                    246: # incrblob-4.*: 
                    247: #
                    248: # Try a couple of error conditions:
                    249: #
                    250: #     4.1 - Attempt to open a row that does not exist.
                    251: #     4.2 - Attempt to open a column that does not exist.
                    252: #     4.3 - Attempt to open a table that does not exist.
                    253: #     4.4 - Attempt to open a database that does not exist.
                    254: #
                    255: #     4.5 - Attempt to open an integer
                    256: #     4.6 - Attempt to open a real value
                    257: #     4.7 - Attempt to open an SQL null
                    258: #
                    259: #     4.8 - Attempt to open an indexed column for writing
                    260: #     4.9 - Attempt to open an indexed column for reading (this works)
                    261: #
                    262: #     4.11 - Attempt to open a column of a view.
                    263: #     4.12 - Attempt to open a column of a virtual table.
                    264: #
                    265: do_test incrblob-4.1 {
                    266:   set rc [catch {
                    267:     set ::blob [db incrblob blobs v 2]
                    268:   } msg ] 
                    269:   list $rc $msg
                    270: } {1 {no such rowid: 2}}
                    271: do_test incrblob-4.2 {
                    272:   set rc [catch {
                    273:     set ::blob [db incrblob blobs blue 1]
                    274:   } msg ] 
                    275:   list $rc $msg
                    276: } {1 {no such column: "blue"}}
                    277: do_test incrblob-4.3 {
                    278:   set rc [catch {
                    279:     set ::blob [db incrblob nosuchtable blue 1]
                    280:   } msg ]
                    281:   list $rc $msg
                    282: } {1 {no such table: main.nosuchtable}}
                    283: do_test incrblob-4.4 {
                    284:   set rc [catch {
                    285:     set ::blob [db incrblob nosuchdb blobs v 1]
                    286:   } msg ] 
                    287:   list $rc $msg
                    288: } {1 {no such table: nosuchdb.blobs}}
                    289: 
                    290: do_test incrblob-4.5 {
                    291:   set rc [catch {
                    292:     set ::blob [db incrblob blobs i 1]
                    293:   } msg ] 
                    294:   list $rc $msg
                    295: } {1 {cannot open value of type integer}}
                    296: do_test incrblob-4.6 {
                    297:   execsql {
                    298:     INSERT INTO blobs(k, v, i) VALUES(123, 567.765, NULL);
                    299:   }
                    300:   set rc [catch {
                    301:     set ::blob [db incrblob blobs v 2]
                    302:   } msg ] 
                    303:   list $rc $msg
                    304: } {1 {cannot open value of type real}}
                    305: do_test incrblob-4.7 {
                    306:   set rc [catch {
                    307:     set ::blob [db incrblob blobs i 2]
                    308:   } msg ] 
                    309:   list $rc $msg
                    310: } {1 {cannot open value of type null}}
                    311: 
                    312: do_test incrblob-4.8.1 {
                    313:   execsql {
                    314:     INSERT INTO blobs(k, v, i) VALUES(X'010203040506070809', 'hello', 'world');
                    315:   }
                    316:   set rc [catch {
                    317:     set ::blob [db incrblob blobs k 3]
                    318:   } msg ] 
                    319:   list $rc $msg
                    320: } {1 {cannot open indexed column for writing}}
                    321: do_test incrblob-4.8.2 {
                    322:   execsql {
                    323:     CREATE TABLE t3(a INTEGER PRIMARY KEY, b);
                    324:     INSERT INTO t3 VALUES(1, 2);
                    325:   }
                    326:   set rc [catch {
                    327:     set ::blob [db incrblob -readonly t3 a 1]
                    328:   } msg ] 
                    329:   list $rc $msg
                    330: } {1 {cannot open value of type null}}
                    331: do_test incrblob-4.8.3 {
                    332:   set rc [catch {
                    333:     set ::blob [db incrblob -readonly t3 rowid 1]
                    334:   } msg ] 
                    335:   list $rc $msg
                    336: } {1 {no such column: "rowid"}}
                    337: 
                    338: do_test incrblob-4.9.1 {
                    339:   set rc [catch {
                    340:     set ::blob [db incrblob -readonly blobs k 3]
                    341:   } msg]
                    342: } {0}
                    343: do_test incrblob-4.9.2 {
                    344:   binary scan [read $::blob] c* c
                    345:   close $::blob
                    346:   set c
                    347: } {1 2 3 4 5 6 7 8 9}
                    348: 
                    349: do_test incrblob-4.10 {
                    350:   set ::blob [db incrblob -readonly blobs k 3]
                    351:   set rc [catch { sqlite3_blob_read $::blob 10 100 } msg]
                    352:   list $rc $msg
                    353: } {1 SQLITE_ERROR}
                    354: do_test incrblob-4.10.2 {
                    355:   close $::blob
                    356: } {}
                    357: 
                    358: ifcapable view {
                    359:   do_test incrblob-4.11 {
                    360:     execsql { CREATE VIEW blobs_view AS SELECT k, v, i FROM blobs }
                    361:     set rc [catch { db incrblob blobs_view v 3 } msg]
                    362:     list $rc $msg
                    363:   } {1 {cannot open view: blobs_view}}
                    364: }
                    365: ifcapable vtab {
                    366:   register_echo_module [sqlite3_connection_pointer db]
                    367:   do_test incrblob-4.12 {
                    368:     execsql { CREATE VIRTUAL TABLE blobs_echo USING echo(blobs) }
                    369:     set rc [catch { db incrblob blobs_echo v 3 } msg]
                    370:     list $rc $msg
                    371:   } {1 {cannot open virtual table: blobs_echo}}
                    372: }
                    373: 
                    374: 
                    375: #------------------------------------------------------------------------
                    376: # incrblob-5.*: 
                    377: #
                    378: #     Test that opening a blob in an attached database works.
                    379: #
                    380: ifcapable attach {
                    381:   do_test incrblob-5.1 {
                    382:     forcedelete test2.db test2.db-journal
                    383:     set ::size [expr [file size [info script]]]
                    384:     execsql {
                    385:       ATTACH 'test2.db' AS aux;
                    386:       CREATE TABLE aux.files(name, text);
                    387:       INSERT INTO aux.files VALUES('this one', zeroblob($::size));
                    388:     }
                    389:     set fd  [db incrblob aux files text 1]
                    390:     fconfigure $fd -translation binary
                    391:     set fd2 [open [info script]]
                    392:     fconfigure $fd2 -translation binary
                    393:     puts -nonewline $fd [read $fd2]
                    394:     close $fd
                    395:     close $fd2
                    396:     set ::text [db one {select text from aux.files}]
                    397:     string length $::text
                    398:   } [file size [info script]]
                    399:   do_test incrblob-5.2 {
                    400:     set fd2 [open [info script]]
                    401:     fconfigure $fd2 -translation binary
                    402:     set ::data [read $fd2]
                    403:     close $fd2
                    404:     set ::data
                    405:   } $::text
                    406: }
                    407: 
                    408: # free memory
                    409: unset -nocomplain ::data
                    410: unset -nocomplain ::text
                    411: 
                    412: #------------------------------------------------------------------------
                    413: # incrblob-6.*: 
                    414: #
                    415: #     Test that opening a blob for write-access is impossible if
                    416: #     another connection has the database RESERVED lock.
                    417: #
                    418: #     Then test that blob writes that take place inside of a
                    419: #     transaction are not visible to external connections until
                    420: #     after the transaction is commited and the blob channel 
                    421: #     closed.
                    422: #
                    423: #     This test does not work with the "memsubsys1" configuration.
                    424: #     Permutation memsubsys1 configures a very small static allocation 
                    425: #     for use as page-cache memory. This causes SQLite to upgrade
                    426: #     to an exclusive lock when writing earlier than usual, which
                    427: #     makes some of these tests fail.
                    428: #
                    429: sqlite3_soft_heap_limit 0
                    430: if {[permutation] != "memsubsys1"} {
                    431:   do_test incrblob-6.1 {
                    432:     sqlite3 db2 test.db
                    433:     execsql {
                    434:       BEGIN;
                    435:       INSERT INTO blobs(k, v, i) VALUES('a', 'different', 'connection');
                    436:     } db2
                    437:   } {}
                    438:   do_test incrblob-6.2 {
                    439:     execsql {
                    440:       SELECT rowid FROM blobs
                    441:     }
                    442:   } {1 2 3}
                    443:   do_test incrblob-6.3 {
                    444:     set rc [catch {
                    445:       db incrblob blobs v 1
                    446:     } msg]
                    447:     list $rc $msg
                    448:   } {1 {database is locked}}
                    449:   do_test incrblob-6.4 {
                    450:     set rc [catch {
                    451:       db incrblob blobs v 3
                    452:     } msg]
                    453:     list $rc $msg
                    454:   } {1 {database is locked}}
                    455:   do_test incrblob-6.5 {
                    456:     set ::blob [db incrblob -readonly blobs v 3]
                    457:     read $::blob
                    458:   } {hello}
                    459:   do_test incrblob-6.6 {
                    460:     close $::blob
                    461:   } {}
                    462:   
                    463:   do_test incrblob-6.7 {
                    464:     set ::blob [db2 incrblob blobs i 4]
                    465:     gets $::blob
                    466:   } {connection}
                    467:   do_test incrblob-6.8 {
                    468:     tell $::blob
                    469:   } {10}
                    470:   do_test incrblob-6.9 {
                    471:     seek $::blob 0
                    472:     puts -nonewline $::blob "invocation"
                    473:     flush $::blob
                    474:   } {}
                    475:   
                    476:   # At this point rollback should be illegal (because 
                    477:   # there is an open blob channel).  But commit is also illegal because
                    478:   # the open blob is read-write.
                    479:   #
                    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 {
                    486:     catchsql {
                    487:       COMMIT;
                    488:     } db2
                    489:   } {1 {cannot commit transaction - SQL statements in progress}}
                    490:   
                    491:   do_test incrblob-6.12 {
                    492:     execsql {
                    493:       SELECT * FROM blobs WHERE rowid = 4;
                    494:     }
                    495:   } {}
                    496:   do_test incrblob-6.13 {
                    497:     close $::blob
                    498:   } {}
                    499:   do_test incrblob-6.14 {
                    500:     catchsql {
                    501:       COMMIT;
                    502:     } db2
                    503:   } {0 {}}
                    504:   do_test incrblob-6.15 {
                    505:     execsql {
                    506:       SELECT * FROM blobs WHERE rowid = 4;
                    507:     }
                    508:   } {a different invocation}
                    509:   db2 close
                    510: }
                    511: sqlite3_soft_heap_limit $cmdlinearg(soft-heap-limit)
                    512: 
                    513: #-----------------------------------------------------------------------
                    514: # The following tests verify the behaviour of the incremental IO
                    515: # APIs in the following cases:
                    516: #
                    517: #     7.1 A row that containing an open blob is modified.
                    518: #
                    519: #     7.2 A CREATE TABLE requires that an overflow page that is part
                    520: #         of an open blob is moved.
                    521: #
                    522: #     7.3 An INCREMENTAL VACUUM moves an overflow page that is part
                    523: #         of an open blob.
                    524: #
                    525: # In the first case above, correct behaviour is for all subsequent
                    526: # read/write operations on the blob-handle to return SQLITE_ABORT.
                    527: # More accurately, blob-handles are invalidated whenever the table
                    528: # they belong to is written to.
                    529: #
                    530: # The second two cases have no external effect. They are testing
                    531: # that the internal cache of overflow page numbers is correctly
                    532: # invalidated.
                    533: #
                    534: do_test incrblob-7.1.0 {
                    535:   execsql {
                    536:     BEGIN;
                    537:     DROP TABLE blobs;
                    538:     CREATE TABLE t1 (a, b, c, d BLOB);
                    539:     INSERT INTO t1(a, b, c, d) VALUES(1, 2, 3, 4);
                    540:     COMMIT;
                    541:   }
                    542: } {}
                    543: 
                    544: foreach {tn arg} {1 "" 2 -readonly} {
                    545: 
                    546:   execsql {
                    547:     UPDATE t1 SET d = zeroblob(10000);
                    548:   }
                    549: 
                    550:   do_test incrblob-7.1.$tn.1 {
                    551:     set ::b [eval db incrblob $arg t1 d 1]
                    552:     binary scan [sqlite3_blob_read $::b 5000 5] c* c
                    553:     set c
                    554:   } {0 0 0 0 0}
                    555:   do_test incrblob-7.1.$tn.2 {
                    556:     execsql {
                    557:       UPDATE t1 SET d = 15;
                    558:     }
                    559:   } {}
                    560:   do_test incrblob-7.1.$tn.3 {
                    561:     set rc [catch { sqlite3_blob_read $::b 5000 5 } msg]
                    562:     list $rc $msg
                    563:   } {1 SQLITE_ABORT}
                    564:   do_test incrblob-7.1.$tn.4 {
                    565:     execsql {
                    566:       SELECT d FROM t1;
                    567:     }
                    568:   } {15}
                    569:   do_test incrblob-7.1.$tn.5 {
                    570:     set rc [catch { close $::b } msg]
                    571:     list $rc $msg
                    572:   } {0 {}}
                    573:   do_test incrblob-7.1.$tn.6 {
                    574:     execsql {
                    575:       SELECT d FROM t1;
                    576:     }
                    577:   } {15}
                    578: 
                    579: }
                    580: 
                    581: set fd [open [info script]]
                    582: fconfigure $fd -translation binary
                    583: set ::data [read $fd 14000]
                    584: close $fd
                    585: 
                    586: db close
                    587: forcedelete test.db test.db-journal
                    588: sqlite3 db test.db
                    589: 
                    590: do_test incrblob-7.2.1 {
                    591:   execsql {
                    592:     PRAGMA auto_vacuum = "incremental";
                    593:     CREATE TABLE t1(a INTEGER PRIMARY KEY, b);        -- root@page3
                    594:     INSERT INTO t1 VALUES(123, $::data);
                    595:   }
                    596:   set ::b [db incrblob -readonly t1 b 123]
                    597:   fconfigure $::b -translation binary
                    598:   read $::b
                    599: } $::data
                    600: do_test incrblob-7.2.2 {
                    601:   execsql {
                    602:     CREATE TABLE t2(a INTEGER PRIMARY KEY, b);        -- root@page4
                    603:   }
                    604:   seek $::b 0
                    605:   read $::b
                    606: } $::data
                    607: do_test incrblob-7.2.3 {
                    608:   close $::b
                    609:   execsql {
                    610:     SELECT rootpage FROM sqlite_master;
                    611:   }
                    612: } {3 4}
                    613: 
                    614: set ::otherdata "[string range $::data 0 1000][string range $::data 1001 end]"
                    615: do_test incrblob-7.3.1 {
                    616:   execsql {
                    617:     INSERT INTO t2 VALUES(456, $::otherdata);
                    618:   }
                    619:   set ::b [db incrblob -readonly t2 b 456]
                    620:   fconfigure $::b -translation binary
                    621:   read $::b
                    622: } $::otherdata
                    623: do_test incrblob-7.3.2 {
                    624:   expr [file size test.db]/1024
                    625: } 30
                    626: do_test incrblob-7.3.3 {
                    627:   execsql {
                    628:     DELETE FROM t1 WHERE a = 123;
                    629:     PRAGMA INCREMENTAL_VACUUM(0);
                    630:   }
                    631:   seek $::b 0
                    632:   read $::b
                    633: } $::otherdata
                    634: 
                    635: # Attempt to write on a read-only blob.  Make sure the error code
                    636: # gets set.  Ticket #2464.
                    637: #
                    638: do_test incrblob-7.4 {
                    639:   set rc [catch {sqlite3_blob_write $::b 10 HELLO} msg]
                    640:   lappend rc $msg
                    641: } {1 SQLITE_READONLY}
                    642: do_test incrblob-7.5 {
                    643:   sqlite3_errcode db
                    644: } {SQLITE_READONLY}
                    645: do_test incrblob-7.6 {
                    646:   sqlite3_errmsg db
                    647: } {attempt to write a readonly database}
                    648: 
                    649: # Test that if either the "offset" or "amount" arguments to
                    650: # sqlite3_blob_write() are less than zero, SQLITE_ERROR is returned.
                    651: # 
                    652: do_test incrblob-8.1 {
                    653:   execsql { INSERT INTO t1 VALUES(314159, 'sqlite') }
                    654:   set ::b [db incrblob t1 b 314159]
                    655:   fconfigure $::b -translation binary
                    656:   set rc [catch {sqlite3_blob_write $::b 10 HELLO -1} msg]
                    657:   lappend rc $msg
                    658: } {1 SQLITE_ERROR}
                    659: do_test incrblob-8.2 {
                    660:   sqlite3_errcode db
                    661: } {SQLITE_ERROR}
                    662: do_test incrblob-8.3 {
                    663:   set rc [catch {sqlite3_blob_write $::b -1 HELLO 5} msg]
                    664:   lappend rc $msg
                    665: } {1 SQLITE_ERROR}
                    666: do_test incrblob-8.4 {
                    667:   sqlite3_errcode db
                    668: } {SQLITE_ERROR}
                    669: do_test incrblob-8.5 {
                    670:   execsql {SELECT b FROM t1 WHERE a = 314159}
                    671: } {sqlite}
                    672: do_test incrblob-8.6 {
                    673:   set rc [catch {sqlite3_blob_write $::b 0 etilqs 6} msg]
                    674:   lappend rc $msg
                    675: } {0 {}}
                    676: do_test incrblob-8.7 {
                    677:   execsql {SELECT b FROM t1 WHERE a = 314159}
                    678: } {etilqs}
                    679: 
                    680: # The following test case exposes an instance in the blob code where
                    681: # 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
                    683: # characters that can be mistaken for printf() formatting directives.
                    684: #
                    685: do_test incrblob-9.1 {
                    686:   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"}}
                    688: 
                    689: 
                    690: finish_test

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>