-C Fix\sa\sbug\sin\sicuOpen()\sin\sfts2.\s(CVS\s6038)
-D 2008-12-18T05:30:26
+C Add\ssavepoint2.test,\sa\sfile\scontaining\ssavepoint\stests\ssimilar\sto\stests\sin\strans.test\sand\savtrans.test.\sAnd\sa\sfew\ssavepoint\sbug\sfixes.\s(CVS\s6039)
+D 2008-12-18T15:45:07
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
F Makefile.in f7e4c81c347b04f7b0f1c1b081a168645d7b8af7
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
F src/auth.c c8b2ab5c8bad4bd90ed7c294694f48269162c627
F src/bitvec.c 4300d311b17fb3c1476623fd895a8feac02a0b08
F src/btmutex.c 63c5cc4ad5715690767ffcb741e185d7bc35ec1a
-F src/btree.c c402a9a15fe62508b332517b162f6fdbcf1bfb47
+F src/btree.c ad51b56b1a90e3c9ad39aabd9368325aba5a6730
F src/btree.h 4f141cf748d2ee7c6d7fc175f64f87a45cd44113
F src/btreeInt.h 7ef2c872371d7508657f8d7a4efe651c741d6ee6
F src/build.c f3e8377cbc0d007b01aab1e7d4fc1d5b296c422e
F src/os_os2.c bed77dc26e3a95ce4a204936b9a1ca6fe612fcc5
F src/os_unix.c 96b4a6e87335ba943455740f311b4dfb63f26756
F src/os_win.c 496e3ceb499aedc63622a89ef76f7af2dd902709
-F src/pager.c dd1aba4a1dc246b72d15fa9ffcf59902cea51d54
+F src/pager.c 9c1663c9406743f30cdad532c01c47f71bfac577
F src/pager.h 7191294438881eb4d13eedade97891e8dc993905
F src/parse.y 4d0e33a702dc3ea7b69d8ae1914b3fbd32e46057
F src/pcache.c 16dc8da6e6ba6250f8dfd9ee46036db1cbceedc6
F test/rtree.test b85fd4f0861a40ca366ac195e363be2528dcfadf
F test/safety.test b69e2b2dd5d52a3f78e216967086884bbc1a09c6
F test/savepoint.test fdad3b61f4a00a96cd773ca0c758cf2f53918ae3
+F test/savepoint2.test dcaf442a9eea4e91c27fce339fd74c3eaa66577e
F test/schema.test a8b000723375fd42c68d310091bdbd744fde647c
F test/schema2.test 35e1c9696443d6694c8980c411497c2b5190d32e
F test/select1.test d0a4cad954fd41c030ec16ffbd2d08a4c0548742
F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
-P 78401b33febf678cfeec2a35514eb4172de420ab
-R 09419362acc9ec794afd36b3528f0694
+P b9c722bd96b44e0fabd1564ddd982d2aabb7047c
+R e8991f966fc1a93805d33d53f39d5eb2
U danielk1977
-Z 152f2d9b602bfeed8b492ec878934f0b
+Z 23f7ea8ae683063fc7d5590449b66501
-b9c722bd96b44e0fabd1564ddd982d2aabb7047c
\ No newline at end of file
+98a53d91f6c0c2692d3b56687fdaba8eeab0959d
\ No newline at end of file
** May you share freely, never taking more than you give.
**
*************************************************************************
-** $Id: btree.c,v 1.549 2008/12/17 17:30:26 danielk1977 Exp $
+** $Id: btree.c,v 1.550 2008/12/18 15:45:07 danielk1977 Exp $
**
** This file implements a external (disk-based) database using BTrees.
** See the header comment on "btreeInt.h" for additional information.
trans_begun:
if( rc==SQLITE_OK && wrflag ){
+ /* This call makes sure that the pager has the correct number of
+ ** open savepoints. If the second parameter is greater than 0 and
+ ** the sub-journal is not already open, then it will be opened here.
+ */
rc = sqlite3PagerOpenSavepoint(pBt->pPager, p->db->nSavepoint);
}
+
btreeIntegrity(p);
sqlite3BtreeLeave(p);
return rc;
** SQL statements. It is illegal to open, release or rollback any
** such savepoints while the statement transaction savepoint is active.
*/
- int iStmtpoint = p->db->nSavepoint + 1;
- rc = sqlite3PagerOpenSavepoint(pBt->pPager, iStmtpoint);
+ rc = sqlite3PagerOpenSavepoint(pBt->pPager, p->db->nSavepoint+1);
}
pBt->inStmt = 1;
}
/*
** The second argument to this function, op, is always SAVEPOINT_ROLLBACK
** or SAVEPOINT_RELEASE. This function either releases or rolls back the
-** savepoint identified by parameter iSavepoint, depending on the value of
-** op.
+** savepoint identified by parameter iSavepoint, depending on the value
+** of op.
+**
+** Normally, iSavepoint is greater than or equal to zero. However, if op is
+** SAVEPOINT_ROLLBACK, then iSavepoint may also be -1. In this case the
+** contents of the entire transaction are rolled back. This is different
+** from a normal transaction rollback, as no locks are released and the
+** transaction remains open.
*/
int sqlite3BtreeSavepoint(Btree *p, int op, int iSavepoint){
int rc = SQLITE_OK;
** file simultaneously, or one process from reading the database while
** another is writing.
**
-** @(#) $Id: pager.c,v 1.515 2008/12/17 17:30:26 danielk1977 Exp $
+** @(#) $Id: pager.c,v 1.516 2008/12/18 15:45:07 danielk1977 Exp $
*/
#ifndef SQLITE_OMIT_DISKIO
#include "sqliteInt.h"
if( nJRec==0 ){
nJRec = (szJ - pPager->journalOff) / (pPager->pageSize+8);
}
- for(ii=0; rc==SQLITE_OK && ii<nJRec; ii++){
+ for(ii=0; rc==SQLITE_OK && ii<nJRec && pPager->journalOff<szJ; ii++){
rc = pager_playback_one_page(pPager, 1, pPager->journalOff, pDone);
assert( rc!=SQLITE_DONE );
}
if( pList->pgno<=pPager->dbSize && 0==(pList->flags&PGHDR_DONT_WRITE) ){
i64 offset = (pList->pgno-1)*(i64)pPager->pageSize;
char *pData = CODEC2(pPager, pList->pData, pList->pgno, 6);
+
PAGERTRACE4("STORE %d page %d hash(%08x)\n",
PAGERID(pPager), pList->pgno, pager_pagehash(pList));
IOTRACE(("PGOUT %p %d\n", pPager, pList->pgno));
#ifndef SQLITE_ENABLE_ATOMIC_WRITE
assert( isDirect==0 ); /* isDirect is only true for atomic writes */
#endif
- if( !pPager->changeCountDone ){
+ if( !pPager->changeCountDone && pPager->dbSize>0 ){
/* Open page 1 of the file for writing. */
rc = sqlite3PagerGet(pPager, 1, &pPgHdr);
if( rc!=SQLITE_OK ) return rc;
int sqlite3PagerOpenSavepoint(Pager *pPager, int nSavepoint){
int rc = SQLITE_OK;
- if( nSavepoint>pPager->nSavepoint ){
+ if( nSavepoint>pPager->nSavepoint && pPager->useJournal ){
int ii;
/* Either the sub-journal is open or there are no active savepoints. */
/* Populate the PagerSavepoint structures just allocated. */
for(/* no-op */; ii<nSavepoint; ii++){
- assert( pPager->dbSize>=0 );
+ assert( pPager->dbSizeValid );
aNew[ii].nOrig = pPager->dbSize;
aNew[ii].iOffset = (pPager->journalOpen ? pPager->journalOff : 0);
aNew[ii].iSubRec = pPager->stmtNRec;
--- /dev/null
+# 2008 December 15
+#
+# 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: savepoint2.test,v 1.1 2008/12/18 15:45:07 danielk1977 Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+# Tests in this file are quite similar to those run by trans.test and
+# avtrans.test.
+#
+
+proc signature {} {
+ return [db eval {SELECT count(*), md5sum(x) FROM t3}]
+}
+
+
+
+do_test savepoint2-1 {
+ execsql {
+ PRAGMA cache_size=10;
+ }
+ db close
+ sqlite3 db test.db
+ execsql {
+ BEGIN;
+ CREATE TABLE t3(x TEXT);
+ INSERT INTO t3 VALUES(randstr(10,400));
+ INSERT INTO t3 VALUES(randstr(10,400));
+ INSERT INTO t3 SELECT randstr(10,400) FROM t3;
+ INSERT INTO t3 SELECT randstr(10,400) FROM t3;
+ INSERT INTO t3 SELECT randstr(10,400) FROM t3;
+ INSERT INTO t3 SELECT randstr(10,400) FROM t3;
+ INSERT INTO t3 SELECT randstr(10,400) FROM t3;
+ INSERT INTO t3 SELECT randstr(10,400) FROM t3;
+ INSERT INTO t3 SELECT randstr(10,400) FROM t3;
+ INSERT INTO t3 SELECT randstr(10,400) FROM t3;
+ INSERT INTO t3 SELECT randstr(10,400) FROM t3;
+ COMMIT;
+ SELECT count(*) FROM t3;
+ }
+} {1024}
+
+unset -nocomplain ::sig
+unset -nocomplain SQL
+
+set iterations 20
+
+set SQL(1) {
+ DELETE FROM t3 WHERE random()%10!=0;
+ INSERT INTO t3 SELECT randstr(10,10)||x FROM t3;
+ INSERT INTO t3 SELECT randstr(10,10)||x FROM t3;
+}
+set SQL(2) {
+ DELETE FROM t3 WHERE random()%10!=0;
+ INSERT INTO t3 SELECT randstr(10,10)||x FROM t3;
+ DELETE FROM t3 WHERE random()%10!=0;
+ INSERT INTO t3 SELECT randstr(10,10)||x FROM t3;
+}
+set SQL(3) {
+ UPDATE t3 SET x = randstr(10, 400) WHERE random()%10;
+ INSERT INTO t3 SELECT x FROM t3 WHERE random()%10;
+ DELETE FROM t3 WHERE random()%10;
+}
+set SQL(4) {
+ INSERT INTO t3 SELECT randstr(10,400) FROM t3 WHERE (random()%10 == 0);
+}
+
+
+
+for {set ii 2} {$ii < ($iterations+2)} {incr ii} {
+
+ # Record the database signature. Optionally (every second run) open a
+ # transaction. In all cases open savepoint "one", which may or may
+ # not be a transaction savepoint, depending on whether or not a real
+ # transaction has been opened.
+ #
+ do_test savepoint2-$ii.1 {
+ if {$ii % 2} { execsql BEGIN }
+ set ::sig(one) [signature]
+ execsql "SAVEPOINT one"
+ } {}
+
+ # Execute some SQL on the database. Then rollback to savepoint "one".
+ # Check that the database signature is as it was when "one" was opened.
+ #
+ do_test savepoint2-$ii.2 {
+ execsql $SQL(1)
+ execsql "ROLLBACK to one"
+ signature
+ } $::sig(one)
+ integrity_check savepoint2-$ii.2.1
+
+ # Execute some SQL. Then open savepoint "two". Savepoint "two" is therefore
+ # nested in savepoint "one".
+ #
+ do_test savepoint2-$ii.3 {
+ execsql $SQL(1)
+ set ::sig(two) [signature]
+ execsql "SAVEPOINT two"
+ } {}
+
+ # More SQL changes. The rollback to savepoint "two". Check that the
+ # signature is as it was when savepoint "two" was opened.
+ #
+ do_test savepoint2-$ii.4 {
+ execsql $SQL(2)
+ execsql "ROLLBACK to two"
+ signature
+ } $::sig(two)
+ integrity_check savepoint2-$ii.4.1
+
+ # More SQL changes. The rollback to savepoint "two". Check that the
+ # signature is as it was when savepoint "two" was opened.
+ #
+ do_test savepoint2-$ii.5 {
+ execsql $SQL(2)
+ execsql "SAVEPOINT three"
+ execsql $SQL(3)
+ execsql "RELEASE three"
+ execsql "ROLLBACK to one"
+ signature
+ } $::sig(one)
+
+ # By this point the database is in the same state as it was at the
+ # top of the for{} loop (everything having been rolled back by the
+ # "ROLLBACK TO one" command above). So make a few changes to the
+ # database and COMMIT the open transaction, so that the next iteration
+ # of the for{} loop works on a different dataset.
+ #
+ # The transaction being committed here may have been opened normally using
+ # "BEGIN", or may have been opened using a transaction savepoint created
+ # by the "SAVEPOINT one" statement.
+ #
+ do_test savepoint2-$ii.6 {
+ execsql $SQL(4)
+ execsql COMMIT
+ sqlite3_get_autocommit db
+ } {1}
+ integrity_check savepoint2-$ii.6.1
+}
+
+unset -nocomplain ::sig
+unset -nocomplain SQL
+
+finish_test
+