]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Test cases and corrections to IO and malloc() error handling in incremental blob...
authordanielk1977 <danielk1977@noemail.net>
Fri, 4 May 2007 12:05:56 +0000 (12:05 +0000)
committerdanielk1977 <danielk1977@noemail.net>
Fri, 4 May 2007 12:05:56 +0000 (12:05 +0000)
FossilOrigin-Name: 641e55284e1ba6070073c83ac6ed78ffb29f7e60

manifest
manifest.uuid
src/btree.c
src/tclsqlite.c
src/vdbeaux.c
src/vdbeblob.c
test/incrblob_err.test [new file with mode: 0644]
test/tester.tcl

index 0152f1b0e702c6e8cf69c7e82b41237fa5ecb894..ba3e556ae23241dc97deca3f63581bcca71caf8c 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Fix\sa\sformatting\serrror\sin\sI/O\slogging.\s(CVS\s3914)
-D 2007-05-04T12:01:03
+C Test\scases\sand\scorrections\sto\sIO\sand\smalloc()\serror\shandling\sin\sincremental\sblob\sIO\sfunctions.\s(CVS\s3915)
+D 2007-05-04T12:05:56
 F Makefile.in 8cab54f7c9f5af8f22fd97ddf1ecfd1e1860de62
 F Makefile.linux-gcc 2d8574d1ba75f129aba2019f0b959db380a90935
 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
@@ -59,7 +59,7 @@ F src/alter.c 2c79ec40f65e33deaf90ca493422c74586e481a3
 F src/analyze.c 4bbf5ddf9680587c6d4917e02e378b6037be3651
 F src/attach.c a16ada4a4654a0d126b8223ec9494ebb81bc5c3c
 F src/auth.c 902f4722661c796b97f007d9606bd7529c02597f
-F src/btree.c b88c9265e323b9a55290c39f9712e44050a6162c
+F src/btree.c a47fe8172eb62468f78a2fe4904d2e6b050038fb
 F src/btree.h 2c187d60cf76d74c2b4767294d6b5fa267037ff0
 F src/build.c 02e01ec7907c7d947ab3041fda0e81eaed05db42
 F src/callback.c 6414ed32d55859d0f65067aa5b88d2da27b3af9e
@@ -101,7 +101,7 @@ F src/sqlite.h.in a666300976897eced975b448f722a722b362c6b1
 F src/sqlite3ext.h 7d0d363ea7327e817ef0dfe1b7eee1f171b72890
 F src/sqliteInt.h 5a8c0221a4f11998f46aa76364a9559af8d7c1f7
 F src/table.c 6d0da66dde26ee75614ed8f584a1996467088d06
-F src/tclsqlite.c dde509871614d17f8ab5f3b4bc496b0af07280c7
+F src/tclsqlite.c 0906902b96e4b292ba98499dd380e22d3322f817
 F src/test1.c 29a39fdde51f4612082ecf3f5af54dac93766f87
 F src/test2.c 24458b17ab2f3c90cbc1c8446bd7ffe69be62f88
 F src/test3.c 946ea9d1a8c928656e3c70f0a2fcb8e733a15e86
@@ -129,8 +129,8 @@ F src/vdbe.c a4abf744b5376372a9be30f02ab4b231f353cab1
 F src/vdbe.h 0025259af1939fb264a545816c69e4b5b8d52691
 F src/vdbeInt.h cb02cbbceddf3b40d49012e9f41576f17bcbec97
 F src/vdbeapi.c 37d793559390bec8a00c556f651f21b5f9e589af
-F src/vdbeaux.c 51acaab4275b5fddc7af5e7d1d2594044216ac46
-F src/vdbeblob.c ed2f9b46cc2de8de97d2a4a4ec466c5914d68333
+F src/vdbeaux.c 966d166f9d4079552c7cb48855afe8c1aa331556
+F src/vdbeblob.c 58b3f68f6bc18b58aeab3a31cff083cb4127292f
 F src/vdbefifo.c 3ca8049c561d5d67cbcb94dc909ae9bb68c0bf8f
 F src/vdbemem.c ba98f8572ec4609846b368fa7580db178022f1bb
 F src/vtab.c 89a0d5f39c1beba65a77fdb4d507b831fc5e6baf
@@ -243,6 +243,7 @@ F test/func.test 6727c7729472ae52b5acd86e802f89aa350ba50f
 F test/hook.test 7e7645fd9a033f79cce8fdff151e32715e7ec50a
 F test/in.test 369cb2aa1eab02296b4ec470732fe8c131260b1d
 F test/incrblob.test 5cf5a7693c6cde33eef361d94c00c7bdbc30f563
+F test/incrblob_err.test 9f78c159279c992fa5ce49c06f50b680fc470520
 F test/incrvacuum.test 2173bc075c7b3b96ccf228d737dd4f5c29500dc4
 F test/incrvacuum_ioerr.test 0ebc382bcc2036ec58cf49cc5ffada45f75d907b
 F test/index.test e65df12bed94b2903ee89987115e1578687e9266
@@ -336,7 +337,7 @@ F test/table.test dbdfd06aef054ad5aed8e57a782137d57d5c5528
 F test/tableapi.test 036575a98dcce7c92e9f39056839bbad8a715412
 F test/tclsqlite.test 726c301d35a2c1f4181fb772a607f785dd9e284e
 F test/temptable.test c36f3e5a94507abb64f7ba23deeb4e1a8a8c3821
-F test/tester.tcl dcebe3c5bf15f3b4ba015b4b2237030c1e384941
+F test/tester.tcl 9382df472e0e86cbfddc44ab8c8cc02497bc9c8a
 F test/thread1.test 776c9e459b75ba905193b351926ac4019b049f35
 F test/thread2.test 6d7b30102d600f51b4055ee3a5a19228799049fb
 F test/threadtest1.c 6029d9c5567db28e6dc908a0c63099c3ba6c383b
@@ -473,7 +474,7 @@ F www/tclsqlite.tcl bb0d1357328a42b1993d78573e587c6dcbc964b9
 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
 F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
-P 2a178d0c7950c9d403c0bc43c2043de945fb24e0
-R 2c92eb8d26a624968d9428e7829962d0
-U drh
-Z f76b8b0273f8e85ef3b644774d94b3bf
+P 2d37687a08a7b6b3a7f77f55a7c2e29a1f8731a8
+R 631ed7d60317b63e0f0649096fcada2a
+U danielk1977
+Z dfc7741fad7b57c2866d720631f3b47d
index 32c047af01524618d9c8efa47ecb0748dcf20a1b..f9069a3c1f126884c89182b150b5cb4feb3cbef9 100644 (file)
@@ -1 +1 @@
-2d37687a08a7b6b3a7f77f55a7c2e29a1f8731a8
\ No newline at end of file
+641e55284e1ba6070073c83ac6ed78ffb29f7e60
\ No newline at end of file
index c517c9e0c57e044dd1bd4b42d167a10479541c70..7a786602e3f915f0a6e3bab5f93c3f2442810072 100644 (file)
@@ -9,7 +9,7 @@
 **    May you share freely, never taking more than you give.
 **
 *************************************************************************
-** $Id: btree.c,v 1.371 2007/05/04 08:32:14 danielk1977 Exp $
+** $Id: btree.c,v 1.372 2007/05/04 12:05:56 danielk1977 Exp $
 **
 ** This file implements a external (disk-based) database using BTrees.
 ** For a detailed discussion of BTrees, refer to
@@ -656,6 +656,30 @@ static void unlockAllTables(Btree *p){
 
 static void releasePage(MemPage *pPage);  /* Forward reference */
 
+#ifndef SQLITE_OMIT_INCRBLOB
+/*
+** Invalidate the overflow page-list cache for cursor pCur, if any.
+*/
+static void invalidateOverflowCache(BtCursor *pCur){
+  sqliteFree(pCur->aOverflow);
+  pCur->aOverflow = 0;
+}
+
+/*
+** Invalidate the overflow page-list cache for all cursors opened
+** on the shared btree structure pBt.
+*/
+static void invalidateAllOverflowCache(BtShared *pBt){
+  BtCursor *p;
+  for(p=pBt->pCursor; p; p=p->pNext){
+    invalidateOverflowCache(p);
+  }
+}
+#else
+  #define invalidateOverflowCache(x)
+  #define invalidateAllOverflowCache(x)
+#endif
+
 /*
 ** Save the current cursor position in the variables BtCursor.nKey 
 ** and BtCursor.pKey. The cursor's state is set to CURSOR_REQUIRESEEK.
@@ -695,12 +719,7 @@ static int saveCursorPosition(BtCursor *pCur){
     pCur->eState = CURSOR_REQUIRESEEK;
   }
 
-#ifndef SQLITE_OMIT_INCRBLOB
-  /* Delete the cache of overflow page numbers. */
-  sqliteFree(pCur->aOverflow);
-  pCur->aOverflow = 0;
-#endif
-
+  invalidateOverflowCache(pCur);
   return rc;
 }
 
@@ -2423,19 +2442,11 @@ static int incrVacuumStep(BtShared *pBt, Pgno nFin){
 */
 int sqlite3BtreeIncrVacuum(Btree *p){
   BtShared *pBt = p->pBt;
-  BtCursor *pCur;
-
   assert( pBt->inTransaction==TRANS_WRITE && p->inTrans==TRANS_WRITE );
   if( !pBt->autoVacuum ){
     return SQLITE_DONE;
   }
-#ifndef SQLITE_OMIT_INCRBLOB
-  for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){
-    /* Delete the cache of overflow page numbers. */
-    sqliteFree(pCur->aOverflow);
-    pCur->aOverflow = 0;
-  }
-#endif
+  invalidateAllOverflowCache(pBt);
   return incrVacuumStep(pBt, 0);
 }
 
@@ -2455,15 +2466,7 @@ static int autoVacuumCommit(BtShared *pBt, Pgno *pnTrunc){
   int nRef = sqlite3PagerRefcount(pPager);
 #endif
 
-#ifndef SQLITE_OMIT_INCRBLOB
-  BtCursor *pCur;
-  for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){
-    /* Delete the cache of overflow page numbers. */
-    sqliteFree(pCur->aOverflow);
-    pCur->aOverflow = 0;
-  }
-#endif
-
+  invalidateAllOverflowCache(pBt);
   assert(pBt->autoVacuum);
   if( !pBt->incrVacuum ){
     Pgno nFin = 0;
@@ -2959,9 +2962,7 @@ int sqlite3BtreeCloseCursor(BtCursor *pCur){
   }
   releasePage(pCur->pPage);
   unlockBtreeIfUnused(pBt);
-#ifndef SQLITE_OMIT_INCRBLOB
-  sqliteFree(pCur->aOverflow);
-#endif
+  invalidateOverflowCache(pCur);
   sqliteFree(pCur);
   return SQLITE_OK;
 }
@@ -5801,18 +5802,12 @@ int sqlite3BtreeCreateTable(Btree *p, int *piTable, int flags){
     Pgno pgnoMove;      /* Move a page here to make room for the root-page */
     MemPage *pPageMove; /* The page to move to. */
 
-#ifndef SQLITE_OMIT_INCRBLOB
     /* Creating a new table may probably require moving an existing database
     ** to make room for the new tables root page. In case this page turns
     ** out to be an overflow page, delete all overflow page-map caches
     ** held by open cursors.
     */
-    BtCursor *pCur;
-    for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){
-      sqliteFree(pCur->aOverflow);
-      pCur->aOverflow = 0;
-    }
-#endif
+    invalidateAllOverflowCache(pBt);
 
     /* Read the value of meta[3] from the database to determine where the
     ** root page of the new table should go. meta[3] is the largest root-page
index 1a2567e8cbc8619379376cadca64c0bb16ebdc5a..79429cb1686f3a9fd334d5559b38e3753cba7037 100644 (file)
@@ -12,7 +12,7 @@
 ** A TCL Interface to SQLite.  Append this file to sqlite3.c and
 ** compile the whole thing to build a TCL-enabled version of SQLite.
 **
-** $Id: tclsqlite.c,v 1.182 2007/05/03 16:31:26 danielk1977 Exp $
+** $Id: tclsqlite.c,v 1.183 2007/05/04 12:05:56 danielk1977 Exp $
 */
 #include "tcl.h"
 #include <errno.h>
@@ -153,7 +153,8 @@ static void closeIncrblobChannels(SqliteDb *pDb){
 */
 static int incrblobClose(ClientData instanceData, Tcl_Interp *interp){
   IncrblobChannel *p = (IncrblobChannel *)instanceData;
-  sqlite3_blob_close(p->pBlob);
+  int rc = sqlite3_blob_close(p->pBlob);
+  sqlite3 *db = p->pDb->db;
 
   /* Remove the channel from the SqliteDb.pIncrblob list. */
   if( p->pNext ){
@@ -166,7 +167,13 @@ static int incrblobClose(ClientData instanceData, Tcl_Interp *interp){
     p->pDb->pIncrblob = p->pNext;
   }
 
+  /* Free the IncrblobChannel structure */
   Tcl_Free((char *)p);
+
+  if( rc!=SQLITE_OK ){
+    Tcl_SetResult(interp, (char *)sqlite3_errmsg(db), TCL_VOLATILE);
+    return TCL_ERROR;
+  }
   return TCL_OK;
 }
 
index 83fe3e9fe112707d62a2167717dd3af118c398f9..7cc44306efb71f55f56a5f92d1a89b936a197d73 100644 (file)
@@ -464,12 +464,14 @@ static void freeP3(int p3type, void *p3){
 ** Change N opcodes starting at addr to No-ops.
 */
 void sqlite3VdbeChangeToNoop(Vdbe *p, int addr, int N){
-  VdbeOp *pOp = &p->aOp[addr];
-  while( N-- ){
-    freeP3(pOp->p3type, pOp->p3);
-    memset(pOp, 0, sizeof(pOp[0]));
-    pOp->opcode = OP_Noop;
-    pOp++;
+  if( p && p->aOp ){
+    VdbeOp *pOp = &p->aOp[addr];
+    while( N-- ){
+      freeP3(pOp->p3type, pOp->p3);
+      memset(pOp, 0, sizeof(pOp[0]));
+      pOp->opcode = OP_Noop;
+      pOp++;
+    }
   }
 }
 
index c81ac214103f4f8e58ade0689fb33e55034798c6..9fbdca71a1589086796313df40af669828dd9354 100644 (file)
@@ -10,7 +10,7 @@
 **
 *************************************************************************
 **
-** $Id: vdbeblob.c,v 1.5 2007/05/03 18:14:10 danielk1977 Exp $
+** $Id: vdbeblob.c,v 1.6 2007/05/04 12:05:56 danielk1977 Exp $
 */
 
 #include "sqliteInt.h"
@@ -170,12 +170,14 @@ int sqlite3_blob_open(
       ** and offset cache without causing any IO.
       */
       sqlite3VdbeChangeP2(v, 5, pTab->nCol+1);
-      sqlite3VdbeMakeReady(v, 1, 0, 1, 0);
+      if( !sqlite3MallocFailed() ){
+        sqlite3VdbeMakeReady(v, 1, 0, 1, 0);
+      }
     }
 
     rc = sqlite3SafetyOff(db);
-    if( rc!=SQLITE_OK ){
-      return rc;
+    if( rc!=SQLITE_OK || sqlite3MallocFailed() ){
+      goto blob_open_out;
     }
 
     sqlite3_bind_int64((sqlite3_stmt *)v, 1, iRow);
@@ -222,11 +224,11 @@ int sqlite3_blob_open(
   }
 
 blob_open_out:
+  zErr[sizeof(zErr)-1] = '\0';
   if( rc!=SQLITE_OK || sqlite3MallocFailed() ){
     sqlite3_finalize((sqlite3_stmt *)v);
   }
-  zErr[sizeof(zErr)-1] = '\0';
-  sqlite3Error(db, rc, zErr);
+  sqlite3Error(db, rc, (rc==SQLITE_OK?0:zErr));
   return sqlite3ApiExit(db, rc);
 }
 
@@ -235,31 +237,37 @@ blob_open_out:
 */
 int sqlite3_blob_close(sqlite3_blob *pBlob){
   Incrblob *p = (Incrblob *)pBlob;
-  sqlite3_finalize(p->pStmt);
+  sqlite3_stmt *pStmt = p->pStmt;
   sqliteFree(p);
-  return SQLITE_OK;
+  return sqlite3_finalize(pStmt);
 }
 
 /*
 ** Read data from a blob handle.
 */
 int sqlite3_blob_read(sqlite3_blob *pBlob, void *z, int n, int iOffset){
+  int rc = SQLITE_ERROR;
   Incrblob *p = (Incrblob *)pBlob;
-  if( (iOffset+n)>p->nByte ){
-    return SQLITE_ERROR;
+  Vdbe *v = (Vdbe *)(p->pStmt);
+  if( (iOffset+n)<=p->nByte ){
+    rc = sqlite3BtreeData(p->pCsr, iOffset+p->iOffset, n, z);
   }
-  return sqlite3BtreeData(p->pCsr, iOffset+p->iOffset, n, z);
+  v->rc = rc;
+  return sqlite3ApiExit(v->db, v->rc);
 }
 
 /*
 ** Write data to a blob handle.
 */
 int sqlite3_blob_write(sqlite3_blob *pBlob, const void *z, int n, int iOffset){
+  int rc = SQLITE_ERROR;
   Incrblob *p = (Incrblob *)pBlob;
-  if( (iOffset+n)>p->nByte ){
-    return SQLITE_ERROR;
+  Vdbe *v = (Vdbe *)(p->pStmt);
+  if( (iOffset+n)<=p->nByte ){
+    rc = sqlite3BtreePutData(p->pCsr, iOffset+p->iOffset, n, z);
   }
-  return sqlite3BtreePutData(p->pCsr, iOffset+p->iOffset, n, z);
+  v->rc = rc;
+  return sqlite3ApiExit(v->db, v->rc);
 }
 
 /*
diff --git a/test/incrblob_err.test b/test/incrblob_err.test
new file mode 100644 (file)
index 0000000..69a0d7f
--- /dev/null
@@ -0,0 +1,192 @@
+# 2007 May 1
+#
+# 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.
+#
+#***********************************************************************
+#
+# $Id: incrblob_err.test,v 1.1 2007/05/04 12:05:56 danielk1977 Exp $
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+# Usage: do_malloc_test <test number> <options...>
+#
+# The first argument, <test number>, is an integer used to name the
+# tests executed by this proc. Options are as follows:
+#
+#     -tclprep          TCL script to run to prepare test.
+#     -sqlprep          SQL script to run to prepare test.
+#     -tclbody          TCL script to run with malloc failure simulation.
+#     -sqlbody          TCL script to run with malloc failure simulation.
+#     -cleanup          TCL script to run after the test.
+#
+# This command runs a series of tests to verify SQLite's ability
+# to handle an out-of-memory condition gracefully. It is assumed
+# that if this condition occurs a malloc() call will return a
+# NULL pointer. Linux, for example, doesn't do that by default. See
+# the "BUGS" section of malloc(3).
+#
+# Each iteration of a loop, the TCL commands in any argument passed
+# to the -tclbody switch, followed by the SQL commands in any argument
+# passed to the -sqlbody switch are executed. Each iteration the
+# Nth call to sqliteMalloc() is made to fail, where N is increased
+# each time the loop runs starting from 1. When all commands execute
+# successfully, the loop ends.
+#
+proc do_malloc_test {tn args} {
+  array unset ::mallocopts 
+  array set ::mallocopts $args
+
+  set ::go 1
+  for {set ::n 1} {$::go && $::n < 50000} {incr ::n} {
+    do_test incrblob_err-$tn.$::n {
+
+      # Remove all traces of database files test.db and test2.db from the files
+      # system. Then open (empty database) "test.db" with the handle [db].
+      # 
+      sqlite_malloc_fail 0
+      catch {db close} 
+      catch {file delete -force test.db}
+      catch {file delete -force test.db-journal}
+      catch {file delete -force test2.db}
+      catch {file delete -force test2.db-journal}
+      catch {sqlite3 db test.db} 
+      set ::DB [sqlite3_connection_pointer db]
+
+      # Execute any -tclprep and -sqlprep scripts.
+      #
+      if {[info exists ::mallocopts(-tclprep)]} {
+        eval $::mallocopts(-tclprep)
+      }
+      if {[info exists ::mallocopts(-sqlprep)]} {
+        execsql $::mallocopts(-sqlprep)
+      }
+
+      # Now set the ${::n}th malloc() to fail and execute the -tclbody and
+      # -sqlbody scripts.
+      #
+      sqlite_malloc_fail $::n
+      set ::mallocbody {}
+      if {[info exists ::mallocopts(-tclbody)]} {
+        append ::mallocbody "$::mallocopts(-tclbody)\n"
+      }
+      if {[info exists ::mallocopts(-sqlbody)]} {
+        append ::mallocbody "db eval {$::mallocopts(-sqlbody)}"
+      }
+      set v [catch $::mallocbody msg]
+
+      # If the test fails (if $v!=0) and the database connection actually
+      # exists, make sure the failure code is SQLITE_NOMEM.
+      if {$v && [info command db]=="db" && [info exists ::mallocopts(-sqlbody)]
+              && [db errorcode]!=7} {
+        set v 999
+      }
+
+      set leftover [lindex [sqlite_malloc_stat] 2]
+      if {$leftover>0} {
+        if {$leftover>1} {puts "\nLeftover: $leftover\nReturn=$v  Message=$msg"}
+        set ::go 0
+        if {$v} {
+          puts "\nError message returned: $msg"
+        } else {
+          set v {1 1}
+        }
+      } else {
+        set v2 [expr {$msg=="" || $msg=="out of memory"}]
+        if {!$v2} {puts "\nError message returned: $msg"}
+        lappend v $v2
+      }
+    } {1 1}
+
+    if {[info exists ::mallocopts(-cleanup)]} {
+      catch [list uplevel #0 $::mallocopts(-cleanup)] msg
+    }
+  }
+  unset ::mallocopts
+}
+
+set ::fd [open [info script]]
+set ::data [read $::fd]
+close $::fd
+
+do_malloc_test 1 -tclprep {
+  set bytes [file size [info script]]
+  execsql {
+    CREATE TABLE blobs(k, v BLOB);
+    INSERT INTO blobs VALUES(1, zeroblob($::bytes));
+  }
+} -tclbody {
+  set ::blob [db incrblob blobs v 1]
+  set rc [catch {puts -nonewline $::blob $::data}]
+  if {$rc} { error "out of memory" }
+} 
+
+do_malloc_test 2 -tclprep {
+  execsql {
+    CREATE TABLE blobs(k, v BLOB);
+    INSERT INTO blobs VALUES(1, $::data);
+  }
+} -tclbody {
+  set ::blob [db incrblob blobs v 1]
+  set rc [catch {set ::r [read $::blob]}]
+  if {$rc} { 
+    error "out of memory" 
+  } elseif {$::r ne $::data} {
+    error "Bad data read..."
+  }
+}
+
+do_malloc_test 3 -tclprep {
+  execsql {
+    CREATE TABLE blobs(k, v BLOB);
+    INSERT INTO blobs VALUES(1, $::data);
+  }
+} -tclbody {
+  set ::blob [db incrblob blobs v 1]
+  set rc [catch {set ::r [read $::blob]}]
+  if {$rc} { 
+    error "out of memory" 
+  } elseif {$::r ne $::data} {
+    error "Bad data read..."
+  }
+  set rc [catch {close $::blob}]
+  if {$rc} { 
+    error "out of memory" 
+  }
+} 
+sqlite_malloc_fail 0
+
+do_ioerr_test incrblob_err-4 -cksum 1 -sqlprep {
+  CREATE TABLE blobs(k, v BLOB);
+  INSERT INTO blobs VALUES(1, $::data);
+} -tclbody {
+  set ::blob [db incrblob blobs v 1]
+  read $::blob
+}
+
+do_ioerr_test incrblob_err-5 -cksum 1 -sqlprep {
+  CREATE TABLE blobs(k, v BLOB);
+  INSERT INTO blobs VALUES(1, zeroblob(length(CAST($::data AS BLOB))));
+} -tclbody {
+  set ::blob [db incrblob blobs v 1]
+  puts -nonewline $::blob $::data
+  close $::blob
+}
+
+do_ioerr_test incrblob_err-6 -cksum 1 -sqlprep {
+  CREATE TABLE blobs(k, v BLOB);
+  INSERT INTO blobs VALUES(1, $::data || $::data || $::data);
+} -tclbody {
+  set ::blob [db incrblob blobs v 1]
+  seek $::blob -20 end
+  puts -nonewline $::blob "12345678900987654321"
+  close $::blob
+}
+
+finish_test
index aed7446719e6c3d1ad3decacf01c18632beb54a0..b35c634f030130968f185067cc7fa75c1f09777a 100644 (file)
@@ -11,7 +11,7 @@
 # This file implements some common TCL routines used for regression
 # testing the SQLite library
 #
-# $Id: tester.tcl,v 1.80 2007/04/28 15:47:45 danielk1977 Exp $
+# $Id: tester.tcl,v 1.81 2007/05/04 12:05:56 danielk1977 Exp $
 
 # Make sure tclsqlite3 was compiled correctly.  Abort now with an
 # error message if not.
@@ -399,7 +399,7 @@ proc do_ioerr_test {testname args} {
 
   set ::go 1
   for {set n $::ioerropts(-start)} {$::go} {incr n} {
-set ::TN $n
+    set ::TN $n
     incr ::ioerropts(-count) -1
     if {$::ioerropts(-count)<0} break
  
@@ -480,6 +480,7 @@ set ::TN $n
       #   1.  We never hit the IO error and the SQL returned OK
       #   2.  An IO error was hit and the SQL failed
       #
+#puts "$s $r $::go - $msg"
       expr { ($s && !$r && !$::go) || (!$s && $r && $::go) }
     } {1}