]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add extra tests and a fix for rollbacks of UNLOCKED transactions.
authordan <dan@noemail.net>
Fri, 21 Aug 2015 14:21:22 +0000 (14:21 +0000)
committerdan <dan@noemail.net>
Fri, 21 Aug 2015 14:21:22 +0000 (14:21 +0000)
FossilOrigin-Name: 82cd837e72ed4cf5821be717369694be29a2997e

manifest
manifest.uuid
src/wal.c
test/unlocked2.test

index ba7247bf361d0c1e2c7d9de00c7b03c328628ea2..dd80228576e983b37e7697fc06022d99496f6e00 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Fix\sa\sproblem\scausing\scorruption\swhen\san\sUNLOCKED\stransaction\sis\srolled\sback.
-D 2015-08-20T20:25:56.029
+C Add\sextra\stests\sand\sa\sfix\sfor\srollbacks\sof\sUNLOCKED\stransactions.
+D 2015-08-21T14:21:22.365
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in 4de3ef40c8b3b75c0c55ff4242a43c8ce1ad90ee
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -402,7 +402,7 @@ F src/vdbesort.c f5009e7a35e3065635d8918b9a31f498a499976b
 F src/vdbetrace.c 8befe829faff6d9e6f6e4dee5a7d3f85cc85f1a0
 F src/vtab.c 082b35a25a26e3d36f365ca8cd73c1922532f05e
 F src/vxworks.h c18586c8edc1bddbc15c004fa16aeb1e1342b4fb
-F src/wal.c 8bb1130dc1876e1c1c3fa082a5b0ec6437feb8e8
+F src/wal.c 37b25bbb52d6a736397d11e85068b1a496970fb2
 F src/wal.h 5aaed8ca6cad1406088042ff8767951a6a3c7b56
 F src/walker.c c253b95b4ee44b21c406e2a1052636c31ea27804
 F src/where.c 909eba3b6db984eb2adfbca9de2c237ee7056adb
@@ -1216,7 +1216,7 @@ F test/unique.test 93f8b2ef5ea51b9495f8d6493429b1fd0f465264
 F test/unique2.test 41e7f83c6827605991160a31380148a9fc5f1339
 F test/unixexcl.test cd6c765f75e50e8e2c2ba763149e5d340ea19825
 F test/unlocked.test d143a871bd874311d4e5c98ce458218ca6b579fd
-F test/unlocked2.test 06a7d5a366bfc6fcaf472a2411f6d45fd9255ed4
+F test/unlocked2.test aca373d7639fd11c946a8e1a78c57bab0f18bc8e
 F test/unordered.test ca7adce0419e4ca0c50f039885e76ed2c531eda8
 F test/update.test 6c68446b8a0a33d522a7c72b320934596a2d7d32
 F test/uri.test 23662b7b61958b0f0e47082de7d06341ccf85d5b
@@ -1368,7 +1368,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b
 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P 3bbc31d515ba9fc920c5cbc7059d3eb1ba9c7f8e
-R 9ac18b47cee85e97c9fcd4362b958c7d
+P 7c36147846484c96023939864417b5624f3bc5f8
+R d431131c35d67ee146c27b397321fd1c
 U dan
-Z 032a41c4b1c95657db216d02c5116d23
+Z 6bf329345f5b33de62ef6fd5bfd9b35f
index ce9cb89059bb6764687ea939fa8627abff310f50..f765222789d6e8e72d9ba6247df3b4d2b4378b37 100644 (file)
@@ -1 +1 @@
-7c36147846484c96023939864417b5624f3bc5f8
\ No newline at end of file
+82cd837e72ed4cf5821be717369694be29a2997e
\ No newline at end of file
index 809ce2b1097421bb83218403ad1d3e566edee95d..ac7e522ff5adb7775a3e945149b542a0ce8838e8 100644 (file)
--- a/src/wal.c
+++ b/src/wal.c
@@ -2635,10 +2635,25 @@ int sqlite3WalLockForCommit(Wal *pWal, PgHdr *pPage1, Bitvec *pAllRead){
               );
               rc = SQLITE_BUSY_SNAPSHOT;
             }else if( (pPg = sqlite3PagerLookup(pPager, aPgno[i])) ){
-              if( sqlite3PagerIswriteable(pPg)==0 ){
-                sqlite3PcacheDrop(pPg);
-              }else{
+              /* Page aPgno[i], which is present in the pager cache, has been
+              ** modified since the current UNLOCKED transaction was started.
+              ** However it was not read by the current transaction, so is not
+              ** a conflict. There are two possibilities: (a) the page was
+              ** allocated at the of the file by the current transaction or 
+              ** (b) was present in the cache at the start of the transaction.
+              **
+              ** For case (a), do nothing. This page will be moved within the
+              ** database file by the commit code to avoid the conflict. The
+              ** call to PagerUnref() is to release the reference grabbed by
+              ** the sqlite3PagerLookup() above.  
+              **
+              ** In case (b), drop the page from the cache - otherwise
+              ** following the snapshot upgrade the cache would be inconsistent
+              ** with the database as stored on disk. */
+              if( sqlite3PagerIswriteable(pPg) ){
                 sqlite3PagerUnref(pPg);
+              }else{
+                sqlite3PcacheDrop(pPg);
               }
             }
           }
index e9c62194a03cb9b06509b39775c9a071d0efb464..1ec9050b60967aa6fe4ed531f3541237b9c3c1a5 100644 (file)
@@ -131,6 +131,18 @@ do_multiclient_test tn {
   do_test 2.$tn.7 { sql3 { PRAGMA integrity_check } } {ok}
 }
 
+#-------------------------------------------------------------------------
+# When an UNLOCKED transaction is opened on a database, the nFree and 
+# iTrunk header fields of the cached version of page 1 are both set 
+# to 0. This allows an UNLOCKED transaction to use its own private 
+# free-page-list, which is merged with the main database free-list when
+# the transaction is committed.
+#
+# The following tests check that nFree/iTrunk are correctly restored if
+# an UNLOCKED transaction is rolled back, and that savepoint rollbacks
+# that occur within UNLOCKED transactions do not incorrectly restore
+# these fields to their on-disk values.
+#
 reset_db
 do_execsql_test 3.0 {
   PRAGMA journal_mode = wal;
@@ -139,23 +151,41 @@ do_execsql_test 3.0 {
   DELETE FROM t1;
 } {wal}
 
-db close
-sqlite3 db test.db
-breakpoint
-
 do_execsql_test 3.1 {
   BEGIN UNLOCKED;
     INSERT INTO t1 VALUES(1, 2);
   ROLLBACK;
 }
 
-do_execsql_test 3.2 {
-  PRAGMA integrity_check;
-} {ok}
+do_execsql_test 3.2 { PRAGMA integrity_check } {ok}
+do_execsql_test 3.3 { PRAGMA freelist_count } {2}
 
-do_execsql_test 3.3 {
+do_execsql_test 3.4.1 {
+  BEGIN UNLOCKED;
+    PRAGMA freelist_count;
+} {2}
+do_execsql_test 3.4.2 {
+  SAVEPOINT xyz;
+    INSERT INTO t1 VALUES(randomblob(1500), NULL);
+    PRAGMA freelist_count;
+} {0}
+do_execsql_test 3.4.3 {
+  ROLLBACK TO xyz;
+} {}
+do_execsql_test 3.4.4 { PRAGMA freelist_count } {0}
+do_execsql_test 3.4.5 { COMMIT; PRAGMA freelist_count } {2}
+do_execsql_test 3.4.6 { PRAGMA integrity_check } {ok}
+
+do_execsql_test 3.5.1 {
+  BEGIN UNLOCKED;
+    UPDATE t1 SET x=randomblob(10) WHERE y=555;
+    PRAGMA freelist_count;
+} {0}
+do_execsql_test 3.5.2 {
+  ROLLBACK;
   PRAGMA freelist_count;
 } {2}
+do_execsql_test 3.5.3 { PRAGMA integrity_check } {ok}
 
 finish_test