]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Make sure a transaction is available for rollback whenever a REDUCE conflict
authordrh <drh@noemail.net>
Thu, 24 Sep 2009 00:09:58 +0000 (00:09 +0000)
committerdrh <drh@noemail.net>
Thu, 24 Sep 2009 00:09:58 +0000 (00:09 +0000)
resolution occurs and there is the possibility to ABORT.
Ticket [4a03edc4c8c]

FossilOrigin-Name: f0c56fa90dc95aff6fe6764b5ab75a90199247b0

manifest
manifest.uuid
src/build.c
src/insert.c
src/sqliteInt.h
src/vdbeaux.c
test/tkt-4a03edc4c8.test [new file with mode: 0644]

index 296531a3b48d5a1e6aafb22cc130825bf15a9c05..36786380a0515d55104376e6c3c15d71d6d3fbf9 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,8 @@
-C More\sfkey\stests.
-D 2009-09-23T18:49:41
+-----BEGIN PGP SIGNED MESSAGE-----
+Hash: SHA1
+
+C Make\ssure\sa\stransaction\sis\savailable\sfor\srollback\swhenever\sa\sREDUCE\sconflict\nresolution\soccurs\sand\sthere\sis\sthe\spossibility\sto\sABORT.\nTicket\s[4a03edc4c8c]
+D 2009-09-24T00:09:58
 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
 F Makefile.in 4ca3f1dd6efa2075bcb27f4dc43eef749877740d
 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@@ -109,7 +112,7 @@ F src/btmutex.c 0f43a75bb5b8147b386e8e1c3e71ba734e3863b7
 F src/btree.c 9c425425784c5d569bc0309c22251698ba906451
 F src/btree.h 577448a890c2ab9b21e6ab74f073526184bceebe
 F src/btreeInt.h 1c86297e69380f6577e7ae67452597dd8d5c2705
-F src/build.c a6bd2dd725847bb4870f1b3f87d64730773c92bb
+F src/build.c c6c8d4ce8c0a464bb25d0c3bfdb27834ad16d902
 F src/callback.c 10d237171472865f58fb07d515737238c9e06688
 F src/complete.c 5ad5c6cd4548211867c204c41a126d73a9fbcea0
 F src/date.c 657ff12ca0f1195b531561afacbb38b772d16638
@@ -122,7 +125,7 @@ F src/global.c 271952d199a8cc59d4ce840b3bbbfd2f30c8ba32
 F src/hash.c ebcaa921ffd9d86f7ea5ae16a0a29d1c871130a7
 F src/hash.h 35b216c13343d0b4f87d9f21969ac55ad72174e1
 F src/hwtime.h 4a1d45f4cae1f402ea19686acf24acf4f0cb53cb
-F src/insert.c e4ca9ed8db8ae84b9c020a3d548fb8d6a355e625
+F src/insert.c 3ff8f07ad36f5b3b2affb8e3fa99c24772b08fc4
 F src/journal.c e00df0c0da8413ab6e1bb7d7cab5665d4a9000d0
 F src/legacy.c 303b4ffcf1ae652fcf5ef635846c563c254564f6
 F src/lempar.c 0c4d1ab0a5ef2b0381eb81a732c54f68f27a574d
@@ -164,7 +167,7 @@ F src/select.c 1d0a13137532321b4364f964e46f057d271691e3
 F src/shell.c d6e64471aafb81f355262533393169a70529847a
 F src/sqlite.h.in 5af8181f815831a8672c3834c60e6b4418448bcc
 F src/sqlite3ext.h 1db7d63ab5de4b3e6b83dd03d1a4e64fef6d2a17
-F src/sqliteInt.h 98ad725d6915a1f1c618ff317e7b09d79efffe57
+F src/sqliteInt.h 6b1fef0ef9aa6bf22e846d96cd3927cf7f55057d
 F src/sqliteLimit.h 504a3161886d2938cbd163054ad620b8356df758
 F src/status.c 237b193efae0cf6ac3f0817a208de6c6c6ef6d76
 F src/table.c cc86ad3d6ad54df7c63a3e807b5783c90411a08d
@@ -210,7 +213,7 @@ F src/vdbe.c a5da14fe8d89f9ad2cd4911a9d7df79c74a6b84c
 F src/vdbe.h 7d5075e3fa4e5587a9be8d5e503857c825490cef
 F src/vdbeInt.h 7afb76c0296f9a2310e565803fa66798ef47e9d5
 F src/vdbeapi.c 524d79eb17bbcbe31c37c908b8e01edc5c684a90
-F src/vdbeaux.c 32d77382469c20aa5a971a8794deb1eafa8d5cb6
+F src/vdbeaux.c c36bb6674d43c8a1f553648c15fcd078c7357262
 F src/vdbeblob.c 3ba0f7ba1b3afce2d37a18e4f437992d430f0eae
 F src/vdbemem.c 0ff2b209fccade3ff6709286057b82ed7f6c1e70
 F src/vtab.c 3e54fe39374e5feb8b174de32a90e7a21966025d
@@ -586,6 +589,7 @@ F test/thread_common.tcl b65e6b1d1d90dc885e10ad080896c6c56eef0819
 F test/threadtest1.c 6029d9c5567db28e6dc908a0c63099c3ba6c383b
 F test/threadtest2.c ace893054fa134af3fc8d6e7cfecddb8e3acefb9
 F test/tkt-2ea2425d34.test 1cf13e6f75d149b3209a0cb32927a82d3d79fb28
+F test/tkt-4a03edc4c8.test 2865e4edbc075b954daa82f8da7cc973033ec76e
 F test/tkt1435.test f8c52c41de6e5ca02f1845f3a46e18e25cadac00
 F test/tkt1443.test bacc311da5c96a227bf8c167e77a30c99f8e8368
 F test/tkt1444.test a9d72f9e942708bd82dde6c707da61c489e213e9
@@ -754,7 +758,14 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
 F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
-P e0a48d53110130de75602603f524539e421a9dba
-R ff71547a957706a79706e81913a173d1
-U shane
-Z 95291c1566a042bd72f53d01f2664d90
+P 2d544bd53d0fb9633aca40841529aec8e7df61f8
+R 3842168b1b7758c2297668effb3e745f
+U drh
+Z 3a3c7d1ce176416e380730f2a219861d
+-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v1.4.6 (GNU/Linux)
+
+iD8DBQFKurjZoxKgR168RlERArl8AJ0WnGHXqijj8D2EisZs22gnQG5PdQCffs5H
+7Kh3yhpsQRwB0Gtl6moTZKc=
+=J9+X
+-----END PGP SIGNATURE-----
index 9262efcd241242bd0c275c049d4b53b90ee28d00..8efea64c3ac27470a23755b8fc14f1ca0412ace3 100644 (file)
@@ -1 +1 @@
-2d544bd53d0fb9633aca40841529aec8e7df61f8
\ No newline at end of file
+f0c56fa90dc95aff6fe6764b5ab75a90199247b0
\ No newline at end of file
index 53d8b32407e784dd8f656af5deda7f43409bc998..544014df22efdb6519fdb68ca17fc656f7330586 100644 (file)
@@ -3493,9 +3493,33 @@ void sqlite3BeginWriteOperation(Parse *pParse, int setStatement, int iDb){
   pToplevel->isMultiWrite |= setStatement;
 }
 
+/*
+** Indicate that the statement currently under construction might write
+** more than one entry (example: deleting one row then inserting another,
+** inserting multiple rows in a table, or inserting a row and index entries.)
+** If an abort occurs after some of these writes have completed, then it will
+** be necessary to undo the completed writes.
+*/
+void sqlite3MultiWrite(Parse *pParse){
+  Parse *pToplevel = sqlite3ParseToplevel(pParse);
+  pToplevel->isMultiWrite = 1;
+}
+
 /* 
-** Set the "may throw abort exception" flag for the statement currently 
-** being coded.
+** The code generator calls this routine if is discovers that it is
+** possible to abort a statement prior to completion.  In order to 
+** perform this abort without corrupting the database, we need to make
+** sure that the statement is protected by a statement transaction.
+**
+** Technically, we only need to set the mayAbort flag if the
+** isMultiWrite flag was previously set.  There is a time dependency
+** such that the abort must occur after the multiwrite.  This makes
+** some statements involving the REPLACE conflict resolution algorithm
+** go a little faster.  But taking advantage of this time dependency
+** makes it more difficult to prove that the code is correct (in 
+** particular, it prevents us from writing an effective
+** implementation of sqlite3AssertMayAbort()) and so we have chosen
+** to take the safe route and skip the optimization.
 */
 void sqlite3MayAbort(Parse *pParse){
   Parse *pToplevel = sqlite3ParseToplevel(pParse);
index 07fd386c2ecd92b0c12891ab368289cabcd1b11c..ba383dcfd160ca544efe5e3c7edd258d1e1858ee 100644 (file)
@@ -1278,6 +1278,7 @@ void sqlite3GenerateConstraintChecks(
           }else{
             sqlite3GenerateRowIndexDelete(pParse, pTab, baseCur, 0);
           }
+          sqlite3MultiWrite(pParse);
           seenReplace = 1;
           break;
         }
@@ -1385,6 +1386,7 @@ void sqlite3GenerateConstraintChecks(
         sqlite3GenerateRowDelete(
             pParse, pTab, baseCur, regR, 0, pTrigger, OE_Replace
         );
+        sqlite3MultiWrite(pParse);
         seenReplace = 1;
         break;
       }
index b028efe35e591862e2f5a6e4e5552cc837dea3df..b6fdad74fc64a2265c76258f7fd370d6f9ff893d 100644 (file)
@@ -2663,7 +2663,8 @@ void sqlite3GenerateConstraintChecks(Parse*,Table*,int,int,
 void sqlite3CompleteInsertion(Parse*, Table*, int, int, int*, int, int, int);
 int sqlite3OpenTableAndIndices(Parse*, Table*, int, int);
 void sqlite3BeginWriteOperation(Parse*, int, int);
-void sqlite3MayAbort(Parse *);
+void sqlite3MultiWrite(Parse*);
+void sqlite3MayAbort(Parse*);
 void sqlite3HaltConstraint(Parse*, int, char*, int);
 Expr *sqlite3ExprDup(sqlite3*,Expr*,int);
 ExprList *sqlite3ExprListDup(sqlite3*,ExprList*,int);
index b5e041b72b600ba4d35cb8ce7833b9279fc32c86..ad298d6461563ca867446ce7cf4b45a5258dbe7c 100644 (file)
@@ -240,7 +240,7 @@ void sqlite3VdbeResolveLabel(Vdbe *p, int x){
   }
 }
 
-#ifdef SQLITE_DEBUG
+#ifdef SQLITE_DEBUG /* sqlite3AssertMayAbort() logic */
 
 /*
 ** The following type and function are used to iterate through all opcodes
@@ -312,7 +312,7 @@ static Op *opIterNext(VdbeOpIter *p){
 
 /*
 ** Check if the program stored in the VM associated with pParse may
-** throw an ABORT exception (causing the statement, but not transaction
+** throw an ABORT exception (causing the statement, but not entire transaction
 ** to be rolled back). This condition is true if the main program or any
 ** sub-programs contains any of the following:
 **
@@ -359,7 +359,7 @@ int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){
   ** from failing.  */
   return ( v->db->mallocFailed || hasAbort==mayAbort );
 }
-#endif
+#endif /* SQLITE_DEBUG - the sqlite3AssertMayAbort() function */
 
 /*
 ** Loop through the program looking for P2 values that are negative
diff --git a/test/tkt-4a03edc4c8.test b/test/tkt-4a03edc4c8.test
new file mode 100644 (file)
index 0000000..649f27d
--- /dev/null
@@ -0,0 +1,46 @@
+# 2009 September 23
+#
+# 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 implements regression tests for SQLite library.
+#
+# This file implements tests to verify that
+# ticket [4a03edc4c8c028c93e9269f64fc5e97f632c1166] has been fixed.  
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+do_test tkt-4a03ed-1.1 {
+  db eval {
+    CREATE TABLE t1(
+      a INTEGER PRIMARY KEY ON CONFLICT REPLACE,
+      b UNIQUE ON CONFLICT FAIL
+    );
+    INSERT INTO t1 VALUES(1, 1);
+    INSERT INTO t1 VALUES(2, 2);
+  }
+  catchsql {
+    BEGIN;
+      INSERT INTO t1 VALUES(1, 2);
+    COMMIT;
+  }
+} {1 {column b is not unique}}
+do_test tkt-4a03ed-1.2 {
+  db eval {
+    PRAGMA integrity_check;
+  }
+} {ok}
+do_test tkt-4a03ed-1.3 {
+  db eval {
+    SELECT * FROM t1 ORDER BY a;
+  }
+} {1 1 2 2}
+
+finish_test