Add savepoint2.test, a file containing savepoint tests similar to tests in trans.test and avtrans.test. And a few savepoint bug fixes. (CVS 6039)
FossilOrigin-Name: 98a53d91f6c0c2692d3b56687fdaba8eeab0959d
This commit is contained in:
parent
78d41832fc
commit
12dd54962d
15
manifest
15
manifest
@ -1,5 +1,5 @@
|
||||
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
|
||||
@ -102,7 +102,7 @@ F src/attach.c 1c35f95da3c62d19de75b44cfefd12c81c1791b3
|
||||
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
|
||||
@ -141,7 +141,7 @@ F src/os_common.h 24525d8b7bce66c374dfc1810a6c9043f3359b60
|
||||
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
|
||||
@ -491,6 +491,7 @@ F test/rowid.test 1c8fc43c60d273e6ea44dfb992db587f3164312c
|
||||
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
|
||||
@ -679,7 +680,7 @@ F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81
|
||||
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
|
||||
|
@ -1 +1 @@
|
||||
b9c722bd96b44e0fabd1564ddd982d2aabb7047c
|
||||
98a53d91f6c0c2692d3b56687fdaba8eeab0959d
|
20
src/btree.c
20
src/btree.c
@ -9,7 +9,7 @@
|
||||
** 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.
|
||||
@ -2060,8 +2060,13 @@ int sqlite3BtreeBeginTrans(Btree *p, int wrflag){
|
||||
|
||||
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;
|
||||
@ -2740,8 +2745,7 @@ int sqlite3BtreeBeginStmt(Btree *p){
|
||||
** 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;
|
||||
}
|
||||
@ -2797,8 +2801,14 @@ int sqlite3BtreeRollbackStmt(Btree *p){
|
||||
/*
|
||||
** 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;
|
||||
|
11
src/pager.c
11
src/pager.c
@ -18,7 +18,7 @@
|
||||
** 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"
|
||||
@ -1649,7 +1649,7 @@ static int pagerPlaybackSavepoint(Pager *pPager, PagerSavepoint *pSavepoint){
|
||||
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 );
|
||||
}
|
||||
@ -2437,6 +2437,7 @@ static int pager_write_pagelist(PgHdr *pList){
|
||||
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));
|
||||
@ -3548,7 +3549,7 @@ static int pager_incr_changecounter(Pager *pPager, int isDirect){
|
||||
#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;
|
||||
@ -3900,7 +3901,7 @@ int sqlite3PagerIsMemdb(Pager *pPager){
|
||||
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. */
|
||||
@ -3925,7 +3926,7 @@ int sqlite3PagerOpenSavepoint(Pager *pPager, int nSavepoint){
|
||||
|
||||
/* 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;
|
||||
|
155
test/savepoint2.test
Normal file
155
test/savepoint2.test
Normal file
@ -0,0 +1,155 @@
|
||||
# 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
|
||||
|
Loading…
Reference in New Issue
Block a user