Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Add test file e_blobwrite.test, containing tests for the sqlite3_blob_write() interface. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
1df77e5f1bd82de4dc92fe28359c3e56 |
User & Date: | dan 2014-11-10 17:53:03.345 |
Context
2014-11-10
| ||
19:16 | New test cases for deleting content out from under a SELECT statement. (check-in: 8289c3e9b4 user: drh tags: trunk) | |
17:53 | Add test file e_blobwrite.test, containing tests for the sqlite3_blob_write() interface. (check-in: 1df77e5f1b user: dan tags: trunk) | |
16:49 | Add the eval() SQL function extension in ext/misc/eval.c. (check-in: 27cf665b95 user: drh tags: trunk) | |
Changes
Changes to src/sqlite.h.in.
︙ | ︙ | |||
5817 5818 5819 5820 5821 5822 5823 | ** See also: [sqlite3_blob_write()]. */ int sqlite3_blob_read(sqlite3_blob *, void *Z, int N, int iOffset); /* ** CAPI3REF: Write Data Into A BLOB Incrementally ** | | | | > > > > > > | | < | | > < < < | 5817 5818 5819 5820 5821 5822 5823 5824 5825 5826 5827 5828 5829 5830 5831 5832 5833 5834 5835 5836 5837 5838 5839 5840 5841 5842 5843 5844 5845 5846 5847 5848 5849 5850 5851 5852 5853 5854 5855 5856 5857 5858 5859 | ** See also: [sqlite3_blob_write()]. */ int sqlite3_blob_read(sqlite3_blob *, void *Z, int N, int iOffset); /* ** CAPI3REF: Write Data Into A BLOB Incrementally ** ** ^(This function is used to write data into an open [BLOB handle] from a ** caller-supplied buffer. N bytes of data are copied from the buffer Z ** into the open BLOB, starting at offset iOffset.)^ ** ** ^(On success, sqlite3_blob_write() returns SQLITE_OK. ** Otherwise, an [error code] or an [extended error code] is returned.)^ ** ^Unless SQLITE_MISUSE is returned, this function sets the ** [database connection] error code and message accessible via ** [sqlite3_errcode()] and [sqlite3_errmsg()] and related functions. ** ** ^If the [BLOB handle] passed as the first argument was not opened for ** writing (the flags parameter to [sqlite3_blob_open()] was zero), ** this function returns [SQLITE_READONLY]. ** ** This function may only modify the contents of the BLOB; it is ** not possible to increase the size of a BLOB using this API. ** ^If offset iOffset is less than N bytes from the end of the BLOB, ** [SQLITE_ERROR] is returned and no data is written. The size of the ** BLOB (and hence the maximum value of N+iOffset) can be determined ** using the [sqlite3_blob_bytes()] interface. ^If N or iOffset are less ** than zero [SQLITE_ERROR] is returned and no data is written. ** ** ^An attempt to write to an expired [BLOB handle] fails with an ** error code of [SQLITE_ABORT]. ^Writes to the BLOB that occurred ** before the [BLOB handle] expired are not rolled back by the ** expiration of the handle, though of course those changes might ** have been overwritten by the statement that expired the BLOB handle ** or by other independent statements. ** ** This routine only works on a [BLOB handle] which has been created ** by a prior successful call to [sqlite3_blob_open()] and which has not ** been closed by [sqlite3_blob_close()]. Passing any other pointer in ** to this routine results in undefined and probably undesirable behavior. ** ** See also: [sqlite3_blob_read()]. */ |
︙ | ︙ |
Changes to src/vdbeblob.c.
︙ | ︙ | |||
372 373 374 375 376 377 378 | db = p->db; sqlite3_mutex_enter(db->mutex); v = (Vdbe*)p->pStmt; if( n<0 || iOffset<0 || (iOffset+n)>p->nByte ){ /* Request is out of range. Return a transient error. */ rc = SQLITE_ERROR; | < < > | 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 | db = p->db; sqlite3_mutex_enter(db->mutex); v = (Vdbe*)p->pStmt; if( n<0 || iOffset<0 || (iOffset+n)>p->nByte ){ /* Request is out of range. Return a transient error. */ rc = SQLITE_ERROR; }else if( v==0 ){ /* If there is no statement handle, then the blob-handle has ** already been invalidated. Return SQLITE_ABORT in this case. */ rc = SQLITE_ABORT; }else{ /* Call either BtreeData() or BtreePutData(). If SQLITE_ABORT is ** returned, clean-up the statement handle. */ assert( db == v->db ); sqlite3BtreeEnterCursor(p->pCsr); rc = xCall(p->pCsr, iOffset+p->iOffset, n, z); sqlite3BtreeLeaveCursor(p->pCsr); if( rc==SQLITE_ABORT ){ sqlite3VdbeFinalize(v); p->pStmt = 0; }else{ v->rc = rc; } } sqlite3Error(db, rc); rc = sqlite3ApiExit(db, rc); sqlite3_mutex_leave(db->mutex); return rc; } /* ** Read data from a blob handle. |
︙ | ︙ |
Added test/e_blobwrite.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 | # 2014 October 30 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix e_blobwrite #-------------------------------------------------------------------------- # EVIDENCE-OF: R-62898-22698 This function is used to write data into an # open BLOB handle from a caller-supplied buffer. N bytes of data are # copied from the buffer Z into the open BLOB, starting at offset # iOffset. # set dots [string repeat . 40] do_execsql_test 1.0 { CREATE TABLE t1(a INTEGER PRIMARY KEY, t TEXT); INSERT INTO t1 VALUES(-1, $dots); INSERT INTO t1 VALUES(-2, $dots); INSERT INTO t1 VALUES(-3, $dots); INSERT INTO t1 VALUES(-4, $dots); INSERT INTO t1 VALUES(-5, $dots); INSERT INTO t1 VALUES(-6, $dots); } proc blob_write_test {tn id iOffset blob nData final} { sqlite3_blob_open db main t1 t $id 1 B # EVIDENCE-OF: R-45864-01884 On success, sqlite3_blob_write() returns # SQLITE_OK. Otherwise, an error code or an extended error code is # returned. # # This block tests the SQLITE_OK case in the requirement above (the # Tcl sqlite3_blob_write() wrapper uses an empty string in place of # "SQLITE_OK"). The error cases are tested by the "blob_write_error_test" # tests below. # set res [sqlite3_blob_write $B $iOffset $blob $nData] uplevel [list do_test $tn.1 [list set {} $res] {}] sqlite3_blob_close $B uplevel [list do_execsql_test $tn.3 "SELECT t FROM t1 WHERE a=$id" $final] } set blob "0123456789012345678901234567890123456789" blob_write_test 1.1 -1 0 $blob 10 { 0123456789.............................. } blob_write_test 1.2 -2 8 $blob 10 { ........0123456789...................... } blob_write_test 1.3 -3 8 $blob 1 { ........0............................... } blob_write_test 1.4 -4 18 $blob 22 { ..................0123456789012345678901 } blob_write_test 1.5 -5 18 $blob 0 { ........................................ } blob_write_test 1.6 -6 0 $blob 40 { 0123456789012345678901234567890123456789 } proc blob_write_error_test {tn B iOffset blob nData errcode errmsg} { # In cases where the underlying sqlite3_blob_write() function returns # SQLITE_OK, the Tcl wrapper returns an empty string. If the underlying # function returns an error, the Tcl wrapper throws an exception with # the error code as the Tcl exception message. # if {$errcode=="SQLITE_OK"} { set ret "" set isError 0 } else { set ret $errcode set isError 1 } set cmd [list sqlite3_blob_write $B $iOffset $blob $nData] uplevel [list do_test $tn.1 [subst -nocommands { list [catch {$cmd} msg] [set msg] }] [list $isError $ret]] # EVIDENCE-OF: R-34782-18311 Unless SQLITE_MISUSE is returned, this # function sets the database connection error code and message # accessible via sqlite3_errcode() and sqlite3_errmsg() and related # functions. # if {$errcode == "SQLITE_MISUSE"} { error "test proc misuse!" } uplevel [list do_test $tn.2 [list sqlite3_errcode db] $errcode] uplevel [list do_test $tn.3 [list sqlite3_errmsg db] $errmsg] } do_execsql_test 2.0 { CREATE TABLE t2(a TEXT, b INTEGER PRIMARY KEY); INSERT INTO t2 VALUES($dots, 43); INSERT INTO t2 VALUES($dots, 44); INSERT INTO t2 VALUES($dots, 45); } # EVIDENCE-OF: R-63341-57517 If the BLOB handle passed as the first # argument was not opened for writing (the flags parameter to # sqlite3_blob_open() was zero), this function returns SQLITE_READONLY. # sqlite3_blob_open db main t2 a 43 0 B blob_write_error_test 2.1 $B 0 $blob 10 \ SQLITE_READONLY {attempt to write a readonly database} sqlite3_blob_close $B # EVIDENCE-OF: R-29804-27366 If offset iOffset is less than N bytes from # the end of the BLOB, SQLITE_ERROR is returned and no data is written. # sqlite3_blob_open db main t2 a 44 3 B blob_write_error_test 2.2.1 $B 31 $blob 10 \ SQLITE_ERROR {SQL logic error or missing database} # Make a successful write to the blob handle. This shows that the # sqlite3_errcode() and sqlite3_errmsg() values are set even if the # blob_write() call succeeds (see requirement in the [blob_write_error_test] # proc). blob_write_error_test 2.2.1 $B 30 $blob 10 SQLITE_OK {not an error} # EVIDENCE-OF: R-58570-38916 If N or iOffset are less than zero # SQLITE_ERROR is returned and no data is written. # blob_write_error_test 2.2.2 $B 31 $blob -1 \ SQLITE_ERROR {SQL logic error or missing database} blob_write_error_test 2.2.3 $B 20 $blob 10 SQLITE_OK {not an error} blob_write_error_test 2.2.4 $B -1 $blob 10 \ SQLITE_ERROR {SQL logic error or missing database} sqlite3_blob_close $B # EVIDENCE-OF: R-20958-54138 An attempt to write to an expired BLOB # handle fails with an error code of SQLITE_ABORT. # do_test 2.3 { sqlite3_blob_open db main t2 a 43 0 B execsql { DELETE FROM t2 WHERE b=43 } } {} blob_write_error_test 2.3.1 $B 5 $blob 5 \ SQLITE_ABORT {callback requested query abort} do_test 2.3.2 { execsql { SELECT 1, 2, 3 } sqlite3_errcode db } {SQLITE_OK} blob_write_error_test 2.3.3 $B 5 $blob 5 \ SQLITE_ABORT {callback requested query abort} sqlite3_blob_close $B # EVIDENCE-OF: R-08382-59936 Writes to the BLOB that occurred before the # BLOB handle expired are not rolled back by the expiration of the # handle, though of course those changes might have been overwritten by # the statement that expired the BLOB handle or by other independent # statements. # # 3.1.*: not rolled back, # 3.2.*: overwritten. # do_execsql_test 3.0 { CREATE TABLE t3(i INTEGER PRIMARY KEY, j TEXT, k TEXT); INSERT INTO t3 VALUES(1, $dots, $dots); INSERT INTO t3 VALUES(2, $dots, $dots); SELECT * FROM t3 WHERE i=1; } { 1 ........................................ ........................................ } sqlite3_blob_open db main t3 j 1 1 B blob_write_error_test 3.1.1 $B 5 $blob 10 SQLITE_OK {not an error} do_execsql_test 3.1.2 { UPDATE t3 SET k = 'xyz' WHERE i=1; SELECT * FROM t3 WHERE i=1; } { 1 .....0123456789......................... xyz } blob_write_error_test 3.1.3 $B 15 $blob 10 \ SQLITE_ABORT {callback requested query abort} sqlite3_blob_close $B do_execsql_test 3.1.4 { SELECT * FROM t3 WHERE i=1; } { 1 .....0123456789......................... xyz } sqlite3_blob_open db main t3 j 2 1 B blob_write_error_test 3.2.1 $B 5 $blob 10 SQLITE_OK {not an error} do_execsql_test 3.2.2 { UPDATE t3 SET j = 'xyz' WHERE i=2; SELECT * FROM t3 WHERE i=2; } { 2 xyz ........................................ } blob_write_error_test 3.2.3 $B 15 $blob 10 \ SQLITE_ABORT {callback requested query abort} sqlite3_blob_close $B do_execsql_test 3.2.4 { SELECT * FROM t3 WHERE i=2; } { 2 xyz ........................................ } finish_test |