From 71b890a3f6f4d7e5d0d47942c562178948eb85d0 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 3 Oct 2007 15:30:52 +0000 Subject: [PATCH] Rollback the transaction if an SQLITE_FULL error is encountered. This is a preliminary fix for ticket #2686. More testing and analysis is needed before we close the ticket. (CVS 4458) FossilOrigin-Name: 0fb6d5a5773c282882e7283e6f8f8c009e238ff4 --- manifest | 15 ++++++++------- manifest.uuid | 2 +- src/vdbeaux.c | 36 ++++++++++++------------------------ test/tkt2686.tcl | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 67 insertions(+), 32 deletions(-) create mode 100644 test/tkt2686.tcl diff --git a/manifest b/manifest index 7bb98dc124..6938377eb2 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\smemory\sleak\sthat\scould\soccur\sduring\serror-state\srecovery.\s(CVS\s4457) -D 2007-10-03T15:22:26 +C Rollback\sthe\stransaction\sif\san\sSQLITE_FULL\serror\sis\sencountered.\nThis\sis\sa\spreliminary\sfix\sfor\sticket\s#2686.\s\sMore\stesting\sand\nanalysis\sis\sneeded\sbefore\swe\sclose\sthe\sticket.\s(CVS\s4458) +D 2007-10-03T15:30:52 F Makefile.in cbfb898945536a8f9ea8b897e1586dd1fdbcc5db F Makefile.linux-gcc 65241babba6faf1152bf86574477baab19190499 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028 @@ -168,7 +168,7 @@ F src/vdbe.c b6c53921512496ef4d7c4f571feb73b7a495db35 F src/vdbe.h 03a0fa17f6753a24d6cb585d7a362944a2c115aa F src/vdbeInt.h 630145b9bfaa19190ab491f52658a7db550f2247 F src/vdbeapi.c 9c2d681b75e4b90c28b9dd01a3f2e5905267f884 -F src/vdbeaux.c e35c851e3c1d18a7b90dbe35ae5e0fc9419a4ed4 +F src/vdbeaux.c 9bb437cb69ae45d7ae2acfcb83264d8bd15b39cc F src/vdbeblob.c 82f51cdf9b0c0af729732fde48c824e498c0a1ca F src/vdbefifo.c 334c838c8f42d61a94813d136019ee566b5dc2f6 F src/vdbemem.c 246d434fa60bde6553490eb686adfd86adcd6712 @@ -461,6 +461,7 @@ F test/tkt2409.test 20318bf6acd9b834b4420548f277b8e3a7420cd1 F test/tkt2450.test 77ed94863f2049c1420288ddfea2d41e5e0971d6 F test/tkt2640.test c513e7992a602a87ef3a2cc9ca1cba4146924e9b F test/tkt2643.test 3f3ebb743da00d4fed4fcf6daed92a0e18e57813 +F test/tkt2686.tcl 2da95620744e11807335ab07f4cc9bbfb1b08001 F test/trace.test 75ffc1b992c780d054748a656e3e7fd674f18567 F test/trans.test b73289992b46d38d9479ecc4fdc03d8edb2413dc F test/trigger1.test b361161cf20614024cc1e52ea0bdec250776b2ae @@ -580,7 +581,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5 -P 7d3f0b149bd2b9c7c12aabb93d022c0ea26f0d74 -R 758b9cd7fcc1c70228ec040144239c4a -U danielk1977 -Z 232289e1446c6deb39d7a5dfa3b4eda2 +P 3d1d13d1eb5817c22956e6e7792783116a828962 +R 2dfb044e805a2e65c272b67cf877a8ea +U drh +Z fad836448ac64c67c038efdc32241a75 diff --git a/manifest.uuid b/manifest.uuid index 4d0adb91e5..7d84e972d5 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3d1d13d1eb5817c22956e6e7792783116a828962 \ No newline at end of file +0fb6d5a5773c282882e7283e6f8f8c009e238ff4 \ No newline at end of file diff --git a/src/vdbeaux.c b/src/vdbeaux.c index ac347c50a5..bdea2a539f 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -1352,28 +1352,16 @@ int sqlite3VdbeHalt(Vdbe *p){ ** transaction will be committed or rolled back as a result of the ** execution of this virtual machine. ** - ** Special errors: + ** If any of the following errors occur: ** - ** If an SQLITE_NOMEM error has occured in a statement that writes to - ** the database, then either a statement or transaction must be rolled - ** back to ensure the tree-structures are in a consistent state. A - ** statement transaction is rolled back if one is open, otherwise the - ** entire transaction must be rolled back. - ** - ** If an SQLITE_IOERR error has occured in a statement that writes to - ** the database, then the entire transaction must be rolled back. The - ** I/O error may have caused garbage to be written to the journal - ** file. Were the transaction to continue and eventually be rolled - ** back that garbage might end up in the database file. - ** - ** In both of the above cases, the Vdbe.errorAction variable is - ** ignored. If the sqlite3.autoCommit flag is false and a transaction - ** is rolled back, it will be set to true. - ** - ** Other errors: - ** - ** No error: + ** SQLITE_NOMEM + ** SQLITE_IOERR + ** SQLITE_FULL + ** SQLITE_INTERRUPT ** + ** Then the internal cache might have been left in an inconsistent + ** state. We need to rollback the statement transaction, if there is + ** one, or the complete transaction if there is no statement transaction. */ if( p->db->mallocFailed ){ @@ -1392,10 +1380,10 @@ int sqlite3VdbeHalt(Vdbe *p){ /* Lock all btrees used by the statement */ sqlite3BtreeMutexArrayEnter(&p->aMutex); - /* Check for one of the special errors - SQLITE_NOMEM or SQLITE_IOERR */ + /* Check for one of the special errors */ mrc = p->rc & 0xff; - isSpecialError = ( - (mrc==SQLITE_NOMEM || mrc==SQLITE_IOERR || mrc==SQLITE_INTERRUPT)?1:0); + isSpecialError = mrc==SQLITE_NOMEM || mrc==SQLITE_IOERR + || mrc==SQLITE_INTERRUPT || mrc==SQLITE_FULL ; if( isSpecialError ){ /* This loop does static analysis of the query to see which of the ** following three categories it falls into: @@ -1444,7 +1432,7 @@ int sqlite3VdbeHalt(Vdbe *p){ if( p->rc==SQLITE_IOERR_BLOCKED && isStatement ){ xFunc = sqlite3BtreeRollbackStmt; p->rc = SQLITE_BUSY; - } else if( p->rc==SQLITE_NOMEM && isStatement ){ + } else if( (p->rc==SQLITE_NOMEM || p->rc==SQLITE_FULL) && isStatement ){ xFunc = sqlite3BtreeRollbackStmt; }else{ /* We are forced to roll back the active transaction. Before doing diff --git a/test/tkt2686.tcl b/test/tkt2686.tcl new file mode 100644 index 0000000000..93ac1711b7 --- /dev/null +++ b/test/tkt2686.tcl @@ -0,0 +1,46 @@ +# 2007 Oct 3 +# +# 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. +# +#*********************************************************************** +# +# This file is to test that ticket #2686 has been fixed. +# +# $Id: tkt2686.tcl,v 1.1 2007/10/03 15:30:52 drh Exp $ +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl + +db eval { + PRAGMA page_size=1024; + PRAGMA max_page_count=50; + PRAGMA auto_vacuum=0; + CREATE TABLE filler (fill); +} +for {set i 1} {$i<2000} {incr i} { + do_test tkt2686-$i.1 { + db eval BEGIN + set rc [catch { + while 1 { + db eval {INSERT INTO filler (fill) VALUES (randstr(1000, 10000)) } + } + } msg] + lappend rc $msg + } {1 {database or disk is full}} + do_test tkt2686-$i.2 { + execsql { + DELETE FROM filler + WHERE rowid <= (SELECT MAX(rowid) FROM filler LIMIT 20) + } + } {} + integrity_check tkt2686-$i.3 + catch {db eval COMMIT} +} + +finish_test -- 2.47.3