1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-05 15:55:57 +03:00

Get the ABORT conflict resolution algorithm working. (CVS 362)

FossilOrigin-Name: 9be4d4c6f12056782966396dca0b8e2d384d0cf2
This commit is contained in:
drh
2002-02-02 18:49:19 +00:00
parent fa86c4127d
commit 663fc63a77
12 changed files with 508 additions and 234 deletions

View File

@@ -1,5 +1,5 @@
C Checkpoint\scode\sadded\sto\sthe\spager.\s\sRegression\stests\swork\sbut\sthe\snew\sAPIs\nhave\snot\sbeen\stested\syet.\s(CVS\s361) C Get\sthe\sABORT\sconflict\sresolution\salgorithm\sworking.\s(CVS\s362)
D 2002-02-02T15:01:16 D 2002-02-02T18:49:20
F Makefile.in 9fa4277413bf1d9cf91365f07d4108d7d87ed2af F Makefile.in 9fa4277413bf1d9cf91365f07d4108d7d87ed2af
F Makefile.template 3372d45f8853afdb70bd30cc6fb50a3cd9069834 F Makefile.template 3372d45f8853afdb70bd30cc6fb50a3cd9069834
F README a4c0ba11354ef6ba0776b400d057c59da47a4cc0 F README a4c0ba11354ef6ba0776b400d057c59da47a4cc0
@@ -19,19 +19,19 @@ F ltmain.sh e9ed72eb1d690f447c13945eaf69e28af531eda1
F publish.sh 5b59f4aff037aafa0e4a3b6fa599495dbd73f360 F publish.sh 5b59f4aff037aafa0e4a3b6fa599495dbd73f360
F sqlite.1 2e2bb0529ef468ade9e4322bd609d0695fb9ded9 F sqlite.1 2e2bb0529ef468ade9e4322bd609d0695fb9ded9
F src/TODO af7f3cab0228e34149cf98e073aa83d45878e7e6 F src/TODO af7f3cab0228e34149cf98e073aa83d45878e7e6
F src/btree.c c796e387da340cb628dc1e41f684fc20253f561e F src/btree.c 94deba286af8e1f665d98378c099da2f7455f291
F src/btree.h 9ead7f54c270d8a554e59352ca7318fdaf411390 F src/btree.h a94bef69f5174461331b6b9ae45a2d84f05af6db
F src/build.c f725dc396d784f723950cf3d47a10f1a69b2f7b7 F src/build.c 397d78ce466e3c22d56de85ae23d8a2777d3b9e6
F src/delete.c f8ad71be53cf18656b6573de65395852fe817f0c F src/delete.c f8ad71be53cf18656b6573de65395852fe817f0c
F src/expr.c a2a87dbd411a508ff89dffa90505ad42dac2f920 F src/expr.c a2a87dbd411a508ff89dffa90505ad42dac2f920
F src/hash.c 8f7c740ef2eaaa8decfa8751f2be30680b123e46 F src/hash.c 8f7c740ef2eaaa8decfa8751f2be30680b123e46
F src/hash.h a5f5b3ce2d086a172c5879b0b06a27a82eac9fac F src/hash.h a5f5b3ce2d086a172c5879b0b06a27a82eac9fac
F src/insert.c 42e89cb227ce744802622886db3572f78e72093f F src/insert.c 051e909cf4c8505aae930dcd773215404e187f23
F src/main.c 300320ba68d3e5b22c2c5b2c07fa884878202181 F src/main.c 300320ba68d3e5b22c2c5b2c07fa884878202181
F src/md5.c 52f677bfc590e09f71d07d7e327bd59da738d07c F src/md5.c 52f677bfc590e09f71d07d7e327bd59da738d07c
F src/os.c 1953080d14098cd45e5bde88941567688efb72b1 F src/os.c 1953080d14098cd45e5bde88941567688efb72b1
F src/os.h a17596ecc7f38a228b83ecdb661fb03ce44726d6 F src/os.h a17596ecc7f38a228b83ecdb661fb03ce44726d6
F src/pager.c f7274d47d8c8a38ce363bfc49f8ccf9d9842e951 F src/pager.c 4059bda97a7e10083b77b7d347fea45426b08589
F src/pager.h b28f004e2f5541dc60cc32db01bf80cf4d056283 F src/pager.h b28f004e2f5541dc60cc32db01bf80cf4d056283
F src/parse.y 88856227ae8472d0f4ae8514bc9561a6ca060690 F src/parse.y 88856227ae8472d0f4ae8514bc9561a6ca060690
F src/printf.c 300a90554345751f26e1fc0c0333b90a66110a1d F src/printf.c 300a90554345751f26e1fc0c0333b90a66110a1d
@@ -40,17 +40,17 @@ F src/select.c fc11d5a8c2bae1b62d8028ffb111c773ad6bf161
F src/shell.c c102dfe388c7618a668c944ff157c49cb48f28e3 F src/shell.c c102dfe388c7618a668c944ff157c49cb48f28e3
F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e
F src/sqlite.h.in f57074c84a2c112a5093ba7a9d9636aa9cacc87c F src/sqlite.h.in f57074c84a2c112a5093ba7a9d9636aa9cacc87c
F src/sqliteInt.h 70fd20107f4953312e76a9630a704c9405161040 F src/sqliteInt.h 41459cf6cae299f66c3ab16b20b8e24443c06089
F src/table.c c89698bd5bb4b8d14722d6ee7e9be014c383d24a F src/table.c c89698bd5bb4b8d14722d6ee7e9be014c383d24a
F src/tclsqlite.c b9cf346e95291cb4c4f1bf5ac1d77db6b8ad023d F src/tclsqlite.c b9cf346e95291cb4c4f1bf5ac1d77db6b8ad023d
F src/test1.c 33efd350dca27c52c58c553c04fd3a6a51f13c1f F src/test1.c 33efd350dca27c52c58c553c04fd3a6a51f13c1f
F src/test2.c d410dbd8a90faa466c3ab694fa0aa57f5a773aa6 F src/test2.c d410dbd8a90faa466c3ab694fa0aa57f5a773aa6
F src/test3.c d6775f95fd91f5b3cf0e2382a28e5aaeb68f745b F src/test3.c d6775f95fd91f5b3cf0e2382a28e5aaeb68f745b
F src/tokenize.c 01a09db6adf933e941db1b781789a0c175be6504 F src/tokenize.c 01a09db6adf933e941db1b781789a0c175be6504
F src/update.c 3fb7c1601bbd379e39881d6b731d3223b822188a F src/update.c 95459f94a061860bf8e5716b3426a5ba85c79103
F src/util.c 8f8973dd55a6ec63be9632fc5de86965c99d6327 F src/util.c 8f8973dd55a6ec63be9632fc5de86965c99d6327
F src/vdbe.c 8e6f1bfff67639b7c3bd07822595fc2ef19f0f34 F src/vdbe.c 3e9d9dba06fb7f6fe85ca3c345eedd32bf27f3a7
F src/vdbe.h 5b1bd518126fc5a30e6ea13fe11de931b32c4b59 F src/vdbe.h 3791edabb212038ae5fbcfa72580204596be01a7
F src/where.c 2dda39367f193194e4c7d2e0dcab31527d9d8aba F src/where.c 2dda39367f193194e4c7d2e0dcab31527d9d8aba
F test/all.test 2a51e5395ac7c2c539689b123b9782a05e3837fe F test/all.test 2a51e5395ac7c2c539689b123b9782a05e3837fe
F test/bigrow.test 8ab252dba108f12ad64e337b0f2ff31a807ac578 F test/bigrow.test 8ab252dba108f12ad64e337b0f2ff31a807ac578
@@ -74,7 +74,7 @@ F test/main.test 1626345b5f630c5398eede500d9354813b76b0fd
F test/malloc.test 70fdd0812e2a57eb746aaf015350f58bb8eee0b1 F test/malloc.test 70fdd0812e2a57eb746aaf015350f58bb8eee0b1
F test/misc1.test 50a5ca3481fc1f3cd6b978bcd6ed04c06f26a1e6 F test/misc1.test 50a5ca3481fc1f3cd6b978bcd6ed04c06f26a1e6
F test/notnull.test b1f3e42fc475b0b5827b27b2e9b562081995ff30 F test/notnull.test b1f3e42fc475b0b5827b27b2e9b562081995ff30
F test/pager.test 59bbc4e3d489529ed33db6e15595789e51056077 F test/pager.test b0c0d00cd5dce0ce21f16926956b195c0ab5044c
F test/printf.test 3cb415073754cb8ff076f26173143c3cd293a9da F test/printf.test 3cb415073754cb8ff076f26173143c3cd293a9da
F test/quick.test 6f023c7a73fc413e6d65b7a1879c79764038dc05 F test/quick.test 6f023c7a73fc413e6d65b7a1879c79764038dc05
F test/quote.test 286db944717afa9a9bf829dd85e59185c65d5435 F test/quote.test 286db944717afa9a9bf829dd85e59185c65d5435
@@ -122,7 +122,7 @@ F www/speed.tcl 83457b2bf6bb430900bd48ca3dd98264d9a916a5
F www/sqlite.tcl 8b5884354cb615049aed83039f8dfe1552a44279 F www/sqlite.tcl 8b5884354cb615049aed83039f8dfe1552a44279
F www/tclsqlite.tcl 829b393d1ab187fd7a5e978631b3429318885c49 F www/tclsqlite.tcl 829b393d1ab187fd7a5e978631b3429318885c49
F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218 F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218
P d0e7cf4a83e6abad7129bed356b7492dddaff474 P aaa53e113ef849e34883ead8ae584c722ad967db
R 819c88d7bb6a0c5001739d080373471b R f2763ccecef4a6c8cd264dd83b3c6a22
U drh U drh
Z 5798e92bdcf7b705413adfa7c6a6e6fe Z fb37183391242f0b96b036b1bf3ee1ea

View File

@@ -1 +1 @@
aaa53e113ef849e34883ead8ae584c722ad967db 9be4d4c6f12056782966396dca0b8e2d384d0cf2

View File

@@ -9,7 +9,7 @@
** May you share freely, never taking more than you give. ** May you share freely, never taking more than you give.
** **
************************************************************************* *************************************************************************
** $Id: btree.c,v 1.46 2002/01/04 03:09:29 drh Exp $ ** $Id: btree.c,v 1.47 2002/02/02 18:49:20 drh Exp $
** **
** This file implements a external (disk-based) database using BTrees. ** This file implements a external (disk-based) database using BTrees.
** For a detailed discussion of BTrees, refer to ** For a detailed discussion of BTrees, refer to
@@ -302,7 +302,8 @@ struct Btree {
Pager *pPager; /* The page cache */ Pager *pPager; /* The page cache */
BtCursor *pCursor; /* A list of all open cursors */ BtCursor *pCursor; /* A list of all open cursors */
PageOne *page1; /* First page of the database */ PageOne *page1; /* First page of the database */
int inTrans; /* True if a transaction is in progress */ u8 inTrans; /* True if a transaction is in progress */
u8 inCkpt; /* True if there is a checkpoint on the transaction */
Hash locks; /* Key: root page number. Data: lock count */ Hash locks; /* Key: root page number. Data: lock count */
}; };
typedef Btree Bt; typedef Btree Bt;
@@ -691,6 +692,7 @@ static void unlockBtreeIfUnused(Btree *pBt){
sqlitepager_unref(pBt->page1); sqlitepager_unref(pBt->page1);
pBt->page1 = 0; pBt->page1 = 0;
pBt->inTrans = 0; pBt->inTrans = 0;
pBt->inCkpt = 0;
} }
} }
@@ -753,6 +755,7 @@ int sqliteBtreeBeginTrans(Btree *pBt){
} }
if( rc==SQLITE_OK ){ if( rc==SQLITE_OK ){
pBt->inTrans = 1; pBt->inTrans = 1;
pBt->inCkpt = 0;
}else{ }else{
unlockBtreeIfUnused(pBt); unlockBtreeIfUnused(pBt);
} }
@@ -770,6 +773,7 @@ int sqliteBtreeCommit(Btree *pBt){
if( pBt->inTrans==0 ) return SQLITE_ERROR; if( pBt->inTrans==0 ) return SQLITE_ERROR;
rc = sqlitepager_commit(pBt->pPager); rc = sqlitepager_commit(pBt->pPager);
pBt->inTrans = 0; pBt->inTrans = 0;
pBt->inCkpt = 0;
unlockBtreeIfUnused(pBt); unlockBtreeIfUnused(pBt);
return rc; return rc;
} }
@@ -788,6 +792,7 @@ int sqliteBtreeRollback(Btree *pBt){
BtCursor *pCur; BtCursor *pCur;
if( pBt->inTrans==0 ) return SQLITE_OK; if( pBt->inTrans==0 ) return SQLITE_OK;
pBt->inTrans = 0; pBt->inTrans = 0;
pBt->inCkpt = 0;
for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){ for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){
if( pCur->pPage ){ if( pCur->pPage ){
sqlitepager_unref(pCur->pPage); sqlitepager_unref(pCur->pPage);
@@ -799,6 +804,61 @@ int sqliteBtreeRollback(Btree *pBt){
return rc; return rc;
} }
/*
** Set the checkpoint for the current transaction. The checkpoint serves
** as a sub-transaction that can be rolled back independently of the
** main transaction. You must start a transaction before starting a
** checkpoint. The checkpoint is ended automatically if the transaction
** commits or rolls back.
**
** Only one checkpoint may be active at a time. It is an error to try
** to start a new checkpoint if another checkpoint is already active.
*/
int sqliteBtreeBeginCkpt(Btree *pBt){
int rc;
if( !pBt->inTrans || pBt->inCkpt ) return SQLITE_ERROR;
rc = sqlitepager_ckpt_begin(pBt->pPager);
pBt->inCkpt = 1;
return rc;
}
/*
** Commit a checkpoint to transaction currently in progress. If no
** checkpoint is active, this is a no-op.
*/
int sqliteBtreeCommitCkpt(Btree *pBt){
int rc;
if( pBt->inCkpt ){
rc = sqlitepager_ckpt_commit(pBt->pPager);
}else{
rc = SQLITE_OK;
}
return rc;
}
/*
** Rollback the checkpoint to the current transaction. If there
** is no active checkpoint or transaction, this routine is a no-op.
**
** All cursors will be invalided by this operation. Any attempt
** to use a cursor that was open at the beginning of this operation
** will result in an error.
*/
int sqliteBtreeRollbackCkpt(Btree *pBt){
int rc;
BtCursor *pCur;
if( pBt->inCkpt==0 ) return SQLITE_OK;
for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){
if( pCur->pPage ){
sqlitepager_unref(pCur->pPage);
pCur->pPage = 0;
}
}
rc = sqlitepager_ckpt_rollback(pBt->pPager);
return rc;
}
/* /*
** Create a new cursor for the BTree whose root is on the page ** Create a new cursor for the BTree whose root is on the page
** iTable. The act of acquiring a cursor gets a read lock on ** iTable. The act of acquiring a cursor gets a read lock on

View File

@@ -13,7 +13,7 @@
** subsystem. See comments in the source code for a detailed description ** subsystem. See comments in the source code for a detailed description
** of what each interface routine does. ** of what each interface routine does.
** **
** @(#) $Id: btree.h,v 1.19 2002/01/04 03:09:30 drh Exp $ ** @(#) $Id: btree.h,v 1.20 2002/02/02 18:49:20 drh Exp $
*/ */
#ifndef _BTREE_H_ #ifndef _BTREE_H_
#define _BTREE_H_ #define _BTREE_H_
@@ -28,6 +28,9 @@ int sqliteBtreeSetCacheSize(Btree*, int);
int sqliteBtreeBeginTrans(Btree*); int sqliteBtreeBeginTrans(Btree*);
int sqliteBtreeCommit(Btree*); int sqliteBtreeCommit(Btree*);
int sqliteBtreeRollback(Btree*); int sqliteBtreeRollback(Btree*);
int sqliteBtreeBeginCkpt(Btree*);
int sqliteBtreeCommitCkpt(Btree*);
int sqliteBtreeRollbackCkpt(Btree*);
int sqliteBtreeCreateTable(Btree*, int*); int sqliteBtreeCreateTable(Btree*, int*);
int sqliteBtreeCreateIndex(Btree*, int*); int sqliteBtreeCreateIndex(Btree*, int*);

View File

@@ -25,7 +25,7 @@
** ROLLBACK ** ROLLBACK
** PRAGMA ** PRAGMA
** **
** $Id: build.c,v 1.70 2002/01/31 15:54:22 drh Exp $ ** $Id: build.c,v 1.71 2002/02/02 18:49:20 drh Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
#include <ctype.h> #include <ctype.h>
@@ -1338,7 +1338,7 @@ void sqliteCopy(
v = sqliteGetVdbe(pParse); v = sqliteGetVdbe(pParse);
if( v ){ if( v ){
int openOp; int openOp;
sqliteBeginWriteOperation(pParse); sqliteBeginMultiWriteOperation(pParse);
addr = sqliteVdbeAddOp(v, OP_FileOpen, 0, 0); addr = sqliteVdbeAddOp(v, OP_FileOpen, 0, 0);
sqliteVdbeChangeP3(v, addr, pFilename->z, pFilename->n); sqliteVdbeChangeP3(v, addr, pFilename->z, pFilename->n);
sqliteVdbeDequoteP3(v, addr); sqliteVdbeDequoteP3(v, addr);
@@ -1493,23 +1493,43 @@ void sqliteRollbackTransaction(Parse *pParse){
/* /*
** Generate VDBE code that prepares for doing an operation that ** Generate VDBE code that prepares for doing an operation that
** might change the database. If we are in the middle of a transaction, ** might change the database. The operation will be atomic in the
** then this sets a checkpoint. If we are not in a transaction, then ** sense that it will either do its changes completely or not at
** start a transaction. ** all. So there is not need to set a checkpoint is a transaction
** is already in effect.
*/ */
void sqliteBeginWriteOperation(Parse *pParse){ void sqliteBeginWriteOperation(Parse *pParse){
Vdbe *v; Vdbe *v;
v = sqliteGetVdbe(pParse); v = sqliteGetVdbe(pParse);
if( v==0 ) return; if( v==0 ) return;
if( pParse->db->flags & SQLITE_InTrans ){ if( (pParse->db->flags & SQLITE_InTrans)==0 ){
/* sqliteVdbeAddOp(v, OP_CheckPoint, 0, 0); */
}else{
sqliteVdbeAddOp(v, OP_Transaction, 0, 0); sqliteVdbeAddOp(v, OP_Transaction, 0, 0);
sqliteVdbeAddOp(v, OP_VerifyCookie, pParse->db->schema_cookie, 0); sqliteVdbeAddOp(v, OP_VerifyCookie, pParse->db->schema_cookie, 0);
pParse->schemaVerified = 1; pParse->schemaVerified = 1;
} }
} }
/*
** Generate VDBE code that prepares for doing an operation that
** might change the database. The operation might not be atomic in
** the sense that an error may be discovered and the operation might
** abort after some changes have been made. If we are in the middle
** of a transaction, then this sets a checkpoint. If we are not in
** a transaction, then start a transaction.
*/
void sqliteBeginMultiWriteOperation(Parse *pParse){
Vdbe *v;
v = sqliteGetVdbe(pParse);
if( v==0 ) return;
if( (pParse->db->flags & SQLITE_InTrans)==0 ){
sqliteVdbeAddOp(v, OP_Transaction, 0, 0);
sqliteVdbeAddOp(v, OP_VerifyCookie, pParse->db->schema_cookie, 0);
pParse->schemaVerified = 1;
}else{
sqliteVdbeAddOp(v, OP_Checkpoint, 0, 0);
}
}
/* /*
** Generate code that concludes an operation that may have changed ** Generate code that concludes an operation that may have changed
** the database. This is a companion function to BeginWriteOperation(). ** the database. This is a companion function to BeginWriteOperation().

View File

@@ -12,7 +12,7 @@
** This file contains C code routines that are called by the parser ** This file contains C code routines that are called by the parser
** to handle INSERT statements in SQLite. ** to handle INSERT statements in SQLite.
** **
** $Id: insert.c,v 1.39 2002/01/31 15:54:22 drh Exp $ ** $Id: insert.c,v 1.40 2002/02/02 18:49:20 drh Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
@@ -79,7 +79,11 @@ void sqliteInsert(
*/ */
v = sqliteGetVdbe(pParse); v = sqliteGetVdbe(pParse);
if( v==0 ) goto insert_cleanup; if( v==0 ) goto insert_cleanup;
sqliteBeginWriteOperation(pParse); if( pSelect ){
sqliteBeginMultiWriteOperation(pParse);
}else{
sqliteBeginWriteOperation(pParse);
}
/* Figure out how many columns of data are supplied. If the data /* Figure out how many columns of data are supplied. If the data
** is coming from a SELECT statement, then this step has to generate ** is coming from a SELECT statement, then this step has to generate

View File

@@ -18,7 +18,7 @@
** file simultaneously, or one process from reading the database while ** file simultaneously, or one process from reading the database while
** another is writing. ** another is writing.
** **
** @(#) $Id: pager.c,v 1.37 2002/02/02 15:01:16 drh Exp $ ** @(#) $Id: pager.c,v 1.38 2002/02/02 18:49:20 drh Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
#include "pager.h" #include "pager.h"
@@ -45,10 +45,6 @@
** threads can be reading or writing while one ** threads can be reading or writing while one
** process is writing. ** process is writing.
** **
** SQLITE_CHECKPOINT The page cache is writing to the database and
** preserving its changes so that it can back them
** out later if need be.
**
** The page cache comes up in SQLITE_UNLOCK. The first time a ** The page cache comes up in SQLITE_UNLOCK. The first time a
** sqlite_page_get() occurs, the state transitions to SQLITE_READLOCK. ** sqlite_page_get() occurs, the state transitions to SQLITE_READLOCK.
** After all pages have been released using sqlite_page_unref(), ** After all pages have been released using sqlite_page_unref(),
@@ -59,20 +55,10 @@
** be in SQLITE_READLOCK before it transitions to SQLITE_WRITELOCK.) ** be in SQLITE_READLOCK before it transitions to SQLITE_WRITELOCK.)
** The sqlite_page_rollback() and sqlite_page_commit() functions ** The sqlite_page_rollback() and sqlite_page_commit() functions
** transition the state from SQLITE_WRITELOCK back to SQLITE_READLOCK. ** transition the state from SQLITE_WRITELOCK back to SQLITE_READLOCK.
**
** The sqlite_ckpt_begin() function moves the state from SQLITE_WRITELOCK
** to SQLITE_CHECKPOINT. The state transitions back to SQLITE_WRITELOCK
** on calls to sqlite_ckpt_commit() or sqlite_ckpt_rollback(). While
** in SQLITE_CHECKPOINT, calls to sqlite_commit() or sqlite_rollback()
** transition directly back to SQLITE_READLOCK.
**
** The code does unequality comparisons on these constants so the order
** must be preserved.
*/ */
#define SQLITE_UNLOCK 0 #define SQLITE_UNLOCK 0
#define SQLITE_READLOCK 1 #define SQLITE_READLOCK 1
#define SQLITE_WRITELOCK 2 #define SQLITE_WRITELOCK 2
#define SQLITE_CHECKPOINT 3
/* /*
@@ -254,12 +240,12 @@ static int pager_unwritelock(Pager *pPager){
int rc; int rc;
PgHdr *pPg; PgHdr *pPg;
if( pPager->state<SQLITE_WRITELOCK ) return SQLITE_OK; if( pPager->state<SQLITE_WRITELOCK ) return SQLITE_OK;
sqlitepager_ckpt_commit(pPager);
sqliteOsClose(&pPager->jfd); sqliteOsClose(&pPager->jfd);
pPager->journalOpen = 0; pPager->journalOpen = 0;
sqliteOsDelete(pPager->zJournal); sqliteOsDelete(pPager->zJournal);
rc = sqliteOsReadLock(&pPager->fd); rc = sqliteOsReadLock(&pPager->fd);
assert( rc==SQLITE_OK ); assert( rc==SQLITE_OK );
sqliteFree( pPager->aInCkpt );
sqliteFree( pPager->aInJournal ); sqliteFree( pPager->aInJournal );
pPager->aInJournal = 0; pPager->aInJournal = 0;
for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){ for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
@@ -279,7 +265,7 @@ static int pager_playback_one_page(Pager *pPager, OsFile *jfd){
PgHdr *pPg; /* An existing page in the cache */ PgHdr *pPg; /* An existing page in the cache */
PageRecord pgRec; PageRecord pgRec;
rc = sqliteOsRead(&pPager->jfd, &pgRec, sizeof(pgRec)); rc = sqliteOsRead(jfd, &pgRec, sizeof(pgRec));
if( rc!=SQLITE_OK ) return rc; if( rc!=SQLITE_OK ) return rc;
/* Sanity checking on the page */ /* Sanity checking on the page */
@@ -383,8 +369,9 @@ end_playback:
** This is similar to playing back the transaction journal but with ** This is similar to playing back the transaction journal but with
** a few extra twists. ** a few extra twists.
** **
** (1) The original size of the database file is stored in ** (1) The number of pages in the database file at the start of
** pPager->ckptSize, not in the journal file itself. ** the checkpoint is stored in pPager->ckptSize, not in the
** journal file itself.
** **
** (2) In addition to playing back the checkpoint journal, also ** (2) In addition to playing back the checkpoint journal, also
** playback all pages of the transaction journal beginning ** playback all pages of the transaction journal beginning
@@ -397,7 +384,7 @@ static int pager_ckpt_playback(Pager *pPager){
/* Truncate the database back to its original size. /* Truncate the database back to its original size.
*/ */
rc = sqliteOsTruncate(&pPager->fd, pPager->ckptSize); rc = sqliteOsTruncate(&pPager->fd, pPager->ckptSize*SQLITE_PAGE_SIZE);
pPager->dbSize = pPager->ckptSize; pPager->dbSize = pPager->ckptSize;
/* Figure out how many records are in the checkpoint journal. /* Figure out how many records are in the checkpoint journal.
@@ -437,14 +424,9 @@ static int pager_ckpt_playback(Pager *pPager){
end_ckpt_playback: end_ckpt_playback:
sqliteOsClose(&pPager->cpfd);
pPager->ckptOpen = 0;
if( rc!=SQLITE_OK ){ if( rc!=SQLITE_OK ){
pager_unwritelock(pPager);
pPager->errMask |= PAGER_ERR_CORRUPT; pPager->errMask |= PAGER_ERR_CORRUPT;
rc = SQLITE_CORRUPT; rc = SQLITE_CORRUPT;
}else{
rc = pager_unwritelock(pPager);
} }
return rc; return rc;
} }
@@ -595,7 +577,6 @@ int sqlitepager_pagecount(Pager *pPager){
int sqlitepager_close(Pager *pPager){ int sqlitepager_close(Pager *pPager){
PgHdr *pPg, *pNext; PgHdr *pPg, *pNext;
switch( pPager->state ){ switch( pPager->state ){
case SQLITE_CHECKPOINT:
case SQLITE_WRITELOCK: { case SQLITE_WRITELOCK: {
sqlitepager_rollback(pPager); sqlitepager_rollback(pPager);
sqliteOsUnlock(&pPager->fd); sqliteOsUnlock(&pPager->fd);
@@ -883,7 +864,7 @@ int sqlitepager_get(Pager *pPager, Pgno pgno, void **ppPage){
}else{ }else{
pPg->inJournal = 0; pPg->inJournal = 0;
} }
if( pPager->aInCkpt && (int)pgno*SQLITE_PAGE_SIZE<=pPager->ckptSize ){ if( pPager->aInCkpt && (int)pgno<=pPager->ckptSize ){
pPg->inCkpt = (pPager->aInCkpt[pgno/8] & (1<<(pgno&7)))!=0; pPg->inCkpt = (pPager->aInCkpt[pgno/8] & (1<<(pgno&7)))!=0;
}else{ }else{
pPg->inCkpt = 0; pPg->inCkpt = 0;
@@ -1111,8 +1092,7 @@ int sqlitepager_write(void *pData){
/* If the checkpoint journal is open and the page is not in it, /* If the checkpoint journal is open and the page is not in it,
** then write the current page to the checkpoint journal. ** then write the current page to the checkpoint journal.
*/ */
if( pPager->ckptOpen && !pPg->inCkpt if( pPager->ckptOpen && !pPg->inCkpt && (int)pPg->pgno<=pPager->ckptSize ){
&& (int)pPg->pgno*SQLITE_PAGE_SIZE < pPager->ckptSize ){
assert( pPg->inJournal ); assert( pPg->inJournal );
rc = sqliteOsWrite(&pPager->cpfd, &pPg->pgno, sizeof(Pgno)); rc = sqliteOsWrite(&pPager->cpfd, &pPg->pgno, sizeof(Pgno));
if( rc==SQLITE_OK ){ if( rc==SQLITE_OK ){
@@ -1268,7 +1248,7 @@ int sqlitepager_ckpt_begin(Pager *pPager){
} }
rc = sqliteOsFileSize(&pPager->jfd, &pPager->ckptJSize); rc = sqliteOsFileSize(&pPager->jfd, &pPager->ckptJSize);
if( rc ) goto ckpt_begin_failed; if( rc ) goto ckpt_begin_failed;
pPager->ckptSize = pPager->dbSize * SQLITE_PAGE_SIZE; pPager->ckptSize = pPager->dbSize;
rc = sqlitepager_opentemp(zTemp, &pPager->cpfd); rc = sqlitepager_opentemp(zTemp, &pPager->cpfd);
if( rc ) goto ckpt_begin_failed; if( rc ) goto ckpt_begin_failed;
pPager->ckptOpen = 1; pPager->ckptOpen = 1;
@@ -1286,10 +1266,16 @@ ckpt_begin_failed:
** Commit a checkpoint. ** Commit a checkpoint.
*/ */
int sqlitepager_ckpt_commit(Pager *pPager){ int sqlitepager_ckpt_commit(Pager *pPager){
assert( pPager->ckptOpen ); if( pPager->ckptOpen ){
sqliteOsClose(&pPager->cpfd); PgHdr *pPg;
sqliteFree(pPager->aInCkpt); sqliteOsClose(&pPager->cpfd);
pPager->ckptOpen = 0; pPager->ckptOpen = 0;
sqliteFree( pPager->aInCkpt );
pPager->aInCkpt = 0;
for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
pPg->inCkpt = 0;
}
}
return SQLITE_OK; return SQLITE_OK;
} }
@@ -1298,11 +1284,12 @@ int sqlitepager_ckpt_commit(Pager *pPager){
*/ */
int sqlitepager_ckpt_rollback(Pager *pPager){ int sqlitepager_ckpt_rollback(Pager *pPager){
int rc; int rc;
assert( pPager->ckptOpen ); if( pPager->ckptOpen ){
rc = pager_ckpt_playback(pPager); rc = pager_ckpt_playback(pPager);
sqliteOsClose(&pPager->cpfd); sqlitepager_ckpt_commit(pPager);
sqliteFree(pPager->aInCkpt); }else{
pPager->ckptOpen = 0; rc = SQLITE_OK;
}
return rc; return rc;
} }

View File

@@ -11,7 +11,7 @@
************************************************************************* *************************************************************************
** Internal interface definitions for SQLite. ** Internal interface definitions for SQLite.
** **
** @(#) $Id: sqliteInt.h,v 1.83 2002/01/31 15:54:22 drh Exp $ ** @(#) $Id: sqliteInt.h,v 1.84 2002/02/02 18:49:21 drh Exp $
*/ */
#include "sqlite.h" #include "sqlite.h"
#include "hash.h" #include "hash.h"
@@ -565,4 +565,5 @@ void sqliteGenerateRowIndexDelete(Vdbe*, Table*, int, char*);
void sqliteGenerateConstraintChecks(Parse*,Table*,int,char*,int,int,int,int); void sqliteGenerateConstraintChecks(Parse*,Table*,int,char*,int,int,int,int);
void sqliteCompleteInsertion(Parse*, Table*, int, char*, int, int); void sqliteCompleteInsertion(Parse*, Table*, int, char*, int, int);
void sqliteBeginWriteOperation(Parse*); void sqliteBeginWriteOperation(Parse*);
void sqliteBeginMultiWriteOperation(Parse*);
void sqliteEndWriteOperation(Parse*); void sqliteEndWriteOperation(Parse*);

View File

@@ -12,7 +12,7 @@
** This file contains C code routines that are called by the parser ** This file contains C code routines that are called by the parser
** to handle UPDATE statements. ** to handle UPDATE statements.
** **
** $Id: update.c,v 1.32 2002/01/31 15:54:22 drh Exp $ ** $Id: update.c,v 1.33 2002/02/02 18:49:21 drh Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
@@ -161,7 +161,7 @@ void sqliteUpdate(
*/ */
v = sqliteGetVdbe(pParse); v = sqliteGetVdbe(pParse);
if( v==0 ) goto update_cleanup; if( v==0 ) goto update_cleanup;
sqliteBeginWriteOperation(pParse); sqliteBeginMultiWriteOperation(pParse);
/* Begin the database scan /* Begin the database scan
*/ */

View File

@@ -30,7 +30,7 @@
** But other routines are also provided to help in building up ** But other routines are also provided to help in building up
** a program instruction by instruction. ** a program instruction by instruction.
** **
** $Id: vdbe.c,v 1.113 2002/01/31 15:54:22 drh Exp $ ** $Id: vdbe.c,v 1.114 2002/02/02 18:49:21 drh Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
#include <ctype.h> #include <ctype.h>
@@ -860,35 +860,35 @@ void sqliteVdbeDelete(Vdbe *p){
** this array, then copy and paste it into this file, if you want. ** this array, then copy and paste it into this file, if you want.
*/ */
static char *zOpName[] = { 0, static char *zOpName[] = { 0,
"Transaction", "Commit", "Rollback", "ReadCookie", "Transaction", "Checkpoint", "Commit", "Rollback",
"SetCookie", "VerifyCookie", "Open", "OpenTemp", "ReadCookie", "SetCookie", "VerifyCookie", "Open",
"OpenWrite", "OpenAux", "OpenWrAux", "Close", "OpenTemp", "OpenWrite", "OpenAux", "OpenWrAux",
"MoveTo", "NewRecno", "PutIntKey", "PutStrKey", "Close", "MoveTo", "NewRecno", "PutIntKey",
"Distinct", "Found", "NotFound", "IsUnique", "PutStrKey", "Distinct", "Found", "NotFound",
"NotExists", "Delete", "Column", "KeyAsData", "IsUnique", "NotExists", "Delete", "Column",
"Recno", "FullKey", "Rewind", "Next", "KeyAsData", "Recno", "FullKey", "Rewind",
"Destroy", "Clear", "CreateIndex", "CreateTable", "Next", "Destroy", "Clear", "CreateIndex",
"Reorganize", "IdxPut", "IdxDelete", "IdxRecno", "CreateTable", "Reorganize", "IdxPut", "IdxDelete",
"IdxGT", "IdxGE", "MemLoad", "MemStore", "IdxRecno", "IdxGT", "IdxGE", "MemLoad",
"ListWrite", "ListRewind", "ListRead", "ListReset", "MemStore", "ListWrite", "ListRewind", "ListRead",
"SortPut", "SortMakeRec", "SortMakeKey", "Sort", "ListReset", "SortPut", "SortMakeRec", "SortMakeKey",
"SortNext", "SortCallback", "SortReset", "FileOpen", "Sort", "SortNext", "SortCallback", "SortReset",
"FileRead", "FileColumn", "AggReset", "AggFocus", "FileOpen", "FileRead", "FileColumn", "AggReset",
"AggIncr", "AggNext", "AggSet", "AggGet", "AggFocus", "AggIncr", "AggNext", "AggSet",
"SetInsert", "SetFound", "SetNotFound", "MakeRecord", "AggGet", "SetInsert", "SetFound", "SetNotFound",
"MakeKey", "MakeIdxKey", "IncrKey", "Goto", "MakeRecord", "MakeKey", "MakeIdxKey", "IncrKey",
"If", "Halt", "ColumnCount", "ColumnName", "Goto", "If", "Halt", "ColumnCount",
"Callback", "NullCallback", "Integer", "String", "ColumnName", "Callback", "NullCallback", "Integer",
"Pop", "Dup", "Pull", "Push", "String", "Pop", "Dup", "Pull",
"MustBeInt", "Add", "AddImm", "Subtract", "Push", "MustBeInt", "Add", "AddImm",
"Multiply", "Divide", "Remainder", "BitAnd", "Subtract", "Multiply", "Divide", "Remainder",
"BitOr", "BitNot", "ShiftLeft", "ShiftRight", "BitAnd", "BitOr", "BitNot", "ShiftLeft",
"AbsValue", "Precision", "Min", "Max", "ShiftRight", "AbsValue", "Precision", "Min",
"Like", "Glob", "Eq", "Ne", "Max", "Like", "Glob", "Eq",
"Lt", "Le", "Gt", "Ge", "Ne", "Lt", "Le", "Gt",
"IsNull", "NotNull", "Negative", "And", "Ge", "IsNull", "NotNull", "Negative",
"Or", "Not", "Concat", "Noop", "And", "Or", "Not", "Concat",
"Strlen", "Substr", "Limit", "Noop", "Strlen", "Substr", "Limit",
}; };
/* /*
@@ -1072,8 +1072,9 @@ int sqliteVdbeExec(
sqlite *db = p->db; /* The database */ sqlite *db = p->db; /* The database */
char **zStack; /* Text stack */ char **zStack; /* Text stack */
Stack *aStack; /* Additional stack information */ Stack *aStack; /* Additional stack information */
int rollbackOnError = 1; /* Do a ROLLBACK if an error is encountered */ int errorAction = OE_Abort; /* Recovery action to do in case of an error */
char zBuf[100]; /* Space to sprintf() an integer */ int undoTransOnError = 0; /* If error, either ROLLBACK or COMMIT */
char zBuf[100]; /* Space to sprintf() an integer */
/* No instruction ever pushes more than a single element onto the /* No instruction ever pushes more than a single element onto the
@@ -1172,7 +1173,7 @@ case OP_Goto: {
case OP_Halt: { case OP_Halt: {
if( pOp->p1!=SQLITE_OK ){ if( pOp->p1!=SQLITE_OK ){
rc = pOp->p1; rc = pOp->p1;
rollbackOnError = pOp->p2!=OE_Fail; errorAction = pOp->p2;
goto abort_due_to_error; goto abort_due_to_error;
}else{ }else{
pc = p->nOp-1; pc = p->nOp-1;
@@ -2319,18 +2320,32 @@ case OP_IncrKey: {
break; break;
} }
/* Opcode: Checkpoint * * *
**
** Begin a checkpoint. A checkpoint is the beginning of a operation that
** is part of a larger transaction but which might need to be rolled back
** itself without effecting the containing transaction. A checkpoint will
** be automatically committed or rollback when the VDBE halts.
*/
case OP_Checkpoint: {
rc = sqliteBtreeBeginCkpt(pBt);
if( rc==SQLITE_OK && db->pBeTemp ){
rc = sqliteBtreeBeginCkpt(pBt);
}
break;
}
/* Opcode: Transaction * * * /* Opcode: Transaction * * *
** **
** Begin a transaction. The transaction ends when a Commit or Rollback ** Begin a transaction. The transaction ends when a Commit or Rollback
** opcode is encountered or whenever there is an execution error that causes ** opcode is encountered. Depending on the ON CONFLICT setting, the
** a script to abort. A transaction is not ended by a Halt. ** transaction might also be rolled back if an error is encountered.
** **
** A write lock is obtained on the database file when a transaction is ** A write lock is obtained on the database file when a transaction is
** started. No other process can read or write the file while the ** started. No other process can read or write the file while the
** transaction is underway. Starting a transaction also creates a ** transaction is underway. Starting a transaction also creates a
** rollback journal. ** rollback journal. A transaction must be started before any changes
** A transaction must be started before any changes can be made to the ** can be made to the database.
** database.
*/ */
case OP_Transaction: { case OP_Transaction: {
int busy = 0; int busy = 0;
@@ -2359,6 +2374,7 @@ case OP_Transaction: {
} }
} }
}while( busy ); }while( busy );
undoTransOnError = 1;
break; break;
} }
@@ -4466,14 +4482,39 @@ default: {
cleanup: cleanup:
Cleanup(p); Cleanup(p);
if( rc!=SQLITE_OK && rollbackOnError ){ if( rc!=SQLITE_OK ){
closeAllCursors(p); switch( errorAction ){
sqliteBtreeRollback(pBt); case OE_Abort: {
if( db->pBeTemp ) sqliteBtreeRollback(db->pBeTemp); if( !undoTransOnError ){
sqliteRollbackInternalChanges(db); sqliteBtreeRollbackCkpt(pBt);
db->flags &= ~SQLITE_InTrans; if( db->pBeTemp ) sqliteBtreeRollbackCkpt(db->pBeTemp);
db->onError = OE_Default; break;
} }
/* Fall through to ROLLBACK */
}
case OE_Rollback: {
sqliteBtreeRollback(pBt);
if( db->pBeTemp ) sqliteBtreeRollback(db->pBeTemp);
sqliteRollbackInternalChanges(db);
db->flags &= ~SQLITE_InTrans;
db->onError = OE_Default;
break;
}
default: {
if( undoTransOnError ){
sqliteBtreeCommit(pBt);
if( db->pBeTemp ) sqliteBtreeCommit(db->pBeTemp);
sqliteCommitInternalChanges(db);
db->flags &= ~SQLITE_InTrans;
db->onError = OE_Default;
}
break;
}
}
}else{
sqliteBtreeCommitCkpt(pBt);
if( db->pBeTemp ) sqliteBtreeCommitCkpt(db->pBeTemp);
}
return rc; return rc;
/* Jump to here if a malloc() fails. It's hard to get a malloc() /* Jump to here if a malloc() fails. It's hard to get a malloc()

View File

@@ -15,7 +15,7 @@
** or VDBE. The VDBE implements an abstract machine that runs a ** or VDBE. The VDBE implements an abstract machine that runs a
** simple program to access and modify the underlying database. ** simple program to access and modify the underlying database.
** **
** $Id: vdbe.h,v 1.39 2002/01/29 18:41:25 drh Exp $ ** $Id: vdbe.h,v 1.40 2002/02/02 18:49:21 drh Exp $
*/ */
#ifndef _SQLITE_VDBE_H_ #ifndef _SQLITE_VDBE_H_
#define _SQLITE_VDBE_H_ #define _SQLITE_VDBE_H_
@@ -69,139 +69,140 @@ typedef struct VdbeOp VdbeOp;
** can be used to renumber these opcodes when new opcodes are inserted. ** can be used to renumber these opcodes when new opcodes are inserted.
*/ */
#define OP_Transaction 1 #define OP_Transaction 1
#define OP_Commit 2 #define OP_Checkpoint 2
#define OP_Rollback 3 #define OP_Commit 3
#define OP_Rollback 4
#define OP_ReadCookie 4 #define OP_ReadCookie 5
#define OP_SetCookie 5 #define OP_SetCookie 6
#define OP_VerifyCookie 6 #define OP_VerifyCookie 7
#define OP_Open 7 #define OP_Open 8
#define OP_OpenTemp 8 #define OP_OpenTemp 9
#define OP_OpenWrite 9 #define OP_OpenWrite 10
#define OP_OpenAux 10 #define OP_OpenAux 11
#define OP_OpenWrAux 11 #define OP_OpenWrAux 12
#define OP_Close 12 #define OP_Close 13
#define OP_MoveTo 13 #define OP_MoveTo 14
#define OP_NewRecno 14 #define OP_NewRecno 15
#define OP_PutIntKey 15 #define OP_PutIntKey 16
#define OP_PutStrKey 16 #define OP_PutStrKey 17
#define OP_Distinct 17 #define OP_Distinct 18
#define OP_Found 18 #define OP_Found 19
#define OP_NotFound 19 #define OP_NotFound 20
#define OP_IsUnique 20 #define OP_IsUnique 21
#define OP_NotExists 21 #define OP_NotExists 22
#define OP_Delete 22 #define OP_Delete 23
#define OP_Column 23 #define OP_Column 24
#define OP_KeyAsData 24 #define OP_KeyAsData 25
#define OP_Recno 25 #define OP_Recno 26
#define OP_FullKey 26 #define OP_FullKey 27
#define OP_Rewind 27 #define OP_Rewind 28
#define OP_Next 28 #define OP_Next 29
#define OP_Destroy 29 #define OP_Destroy 30
#define OP_Clear 30 #define OP_Clear 31
#define OP_CreateIndex 31 #define OP_CreateIndex 32
#define OP_CreateTable 32 #define OP_CreateTable 33
#define OP_Reorganize 33 #define OP_Reorganize 34
#define OP_IdxPut 34 #define OP_IdxPut 35
#define OP_IdxDelete 35 #define OP_IdxDelete 36
#define OP_IdxRecno 36 #define OP_IdxRecno 37
#define OP_IdxGT 37 #define OP_IdxGT 38
#define OP_IdxGE 38 #define OP_IdxGE 39
#define OP_MemLoad 39 #define OP_MemLoad 40
#define OP_MemStore 40 #define OP_MemStore 41
#define OP_ListWrite 41 #define OP_ListWrite 42
#define OP_ListRewind 42 #define OP_ListRewind 43
#define OP_ListRead 43 #define OP_ListRead 44
#define OP_ListReset 44 #define OP_ListReset 45
#define OP_SortPut 45 #define OP_SortPut 46
#define OP_SortMakeRec 46 #define OP_SortMakeRec 47
#define OP_SortMakeKey 47 #define OP_SortMakeKey 48
#define OP_Sort 48 #define OP_Sort 49
#define OP_SortNext 49 #define OP_SortNext 50
#define OP_SortCallback 50 #define OP_SortCallback 51
#define OP_SortReset 51 #define OP_SortReset 52
#define OP_FileOpen 52 #define OP_FileOpen 53
#define OP_FileRead 53 #define OP_FileRead 54
#define OP_FileColumn 54 #define OP_FileColumn 55
#define OP_AggReset 55 #define OP_AggReset 56
#define OP_AggFocus 56 #define OP_AggFocus 57
#define OP_AggIncr 57 #define OP_AggIncr 58
#define OP_AggNext 58 #define OP_AggNext 59
#define OP_AggSet 59 #define OP_AggSet 60
#define OP_AggGet 60 #define OP_AggGet 61
#define OP_SetInsert 61 #define OP_SetInsert 62
#define OP_SetFound 62 #define OP_SetFound 63
#define OP_SetNotFound 63 #define OP_SetNotFound 64
#define OP_MakeRecord 64 #define OP_MakeRecord 65
#define OP_MakeKey 65 #define OP_MakeKey 66
#define OP_MakeIdxKey 66 #define OP_MakeIdxKey 67
#define OP_IncrKey 67 #define OP_IncrKey 68
#define OP_Goto 68 #define OP_Goto 69
#define OP_If 69 #define OP_If 70
#define OP_Halt 70 #define OP_Halt 71
#define OP_ColumnCount 71 #define OP_ColumnCount 72
#define OP_ColumnName 72 #define OP_ColumnName 73
#define OP_Callback 73 #define OP_Callback 74
#define OP_NullCallback 74 #define OP_NullCallback 75
#define OP_Integer 75 #define OP_Integer 76
#define OP_String 76 #define OP_String 77
#define OP_Pop 77 #define OP_Pop 78
#define OP_Dup 78 #define OP_Dup 79
#define OP_Pull 79 #define OP_Pull 80
#define OP_Push 80 #define OP_Push 81
#define OP_MustBeInt 81 #define OP_MustBeInt 82
#define OP_Add 82 #define OP_Add 83
#define OP_AddImm 83 #define OP_AddImm 84
#define OP_Subtract 84 #define OP_Subtract 85
#define OP_Multiply 85 #define OP_Multiply 86
#define OP_Divide 86 #define OP_Divide 87
#define OP_Remainder 87 #define OP_Remainder 88
#define OP_BitAnd 88 #define OP_BitAnd 89
#define OP_BitOr 89 #define OP_BitOr 90
#define OP_BitNot 90 #define OP_BitNot 91
#define OP_ShiftLeft 91 #define OP_ShiftLeft 92
#define OP_ShiftRight 92 #define OP_ShiftRight 93
#define OP_AbsValue 93 #define OP_AbsValue 94
#define OP_Precision 94 #define OP_Precision 95
#define OP_Min 95 #define OP_Min 96
#define OP_Max 96 #define OP_Max 97
#define OP_Like 97 #define OP_Like 98
#define OP_Glob 98 #define OP_Glob 99
#define OP_Eq 99 #define OP_Eq 100
#define OP_Ne 100 #define OP_Ne 101
#define OP_Lt 101 #define OP_Lt 102
#define OP_Le 102 #define OP_Le 103
#define OP_Gt 103 #define OP_Gt 104
#define OP_Ge 104 #define OP_Ge 105
#define OP_IsNull 105 #define OP_IsNull 106
#define OP_NotNull 106 #define OP_NotNull 107
#define OP_Negative 107 #define OP_Negative 108
#define OP_And 108 #define OP_And 109
#define OP_Or 109 #define OP_Or 110
#define OP_Not 110 #define OP_Not 111
#define OP_Concat 111 #define OP_Concat 112
#define OP_Noop 112 #define OP_Noop 113
#define OP_Strlen 113 #define OP_Strlen 114
#define OP_Substr 114 #define OP_Substr 115
#define OP_Limit 115 #define OP_Limit 116
#define OP_MAX 115 #define OP_MAX 116
/* /*
** Prototypes for the VDBE interface. See comments on the implementation ** Prototypes for the VDBE interface. See comments on the implementation

View File

@@ -11,7 +11,7 @@
# This file implements regression tests for SQLite library. The # This file implements regression tests for SQLite library. The
# focus of this script is page cache subsystem. # focus of this script is page cache subsystem.
# #
# $Id: pager.test,v 1.10 2001/09/16 00:13:28 drh Exp $ # $Id: pager.test,v 1.11 2002/02/02 18:49:21 drh Exp $
set testdir [file dirname $argv0] set testdir [file dirname $argv0]
@@ -243,6 +243,163 @@ do_test pager-3.99 {
pager_close $::p1 pager_close $::p1
} {} } {}
# tests of the checkpoint mechanism and api
#
do_test pager-4.0 {
set v [catch {
file delete -force ptf1.db
set ::p1 [pager_open ptf1.db 15]
} msg]
if {$v} {lappend v $msg}
set v
} {0}
do_test pager-4.1 {
set g1 [page_get $::p1 1]
page_write $g1 "Page-1 v0"
for {set i 2} {$i<=20} {incr i} {
set gx [page_get $::p1 $i]
page_write $gx "Page-$i v0"
page_unref $gx
}
pager_commit $::p1
} {}
for {set i 1} {$i<=20} {incr i} {
do_test pager-4.2.$i {
set gx [page_get $p1 $i]
set v [page_read $gx]
page_unref $gx
set v
} "Page-$i v0"
}
do_test pager-4.3 {
lrange [pager_stats $::p1] 0 1
} {ref 1}
do_test pager-4.4 {
lrange [pager_stats $::p1] 8 9
} {state 1}
for {set i 1} {$i<20} {incr i} {
do_test pager-4.5.$i.0 {
set res {}
for {set j 2} {$j<=20} {incr j} {
set gx [page_get $p1 $j]
set value [page_read $gx]
page_unref $gx
set shouldbe "Page-$j v[expr {$i-1}]"
if {$value!=$shouldbe} {
lappend res $value $shouldbe
}
}
set res
} {}
do_test pager-4.5.$i.1 {
page_write $g1 "Page-1 v$i"
lrange [pager_stats $p1] 8 9
} {state 2}
do_test pager-4.5.$i.2 {
for {set j 2} {$j<=20} {incr j} {
set gx [page_get $p1 $j]
page_write $gx "Page-$j v$i"
page_unref $gx
if {$j==$i} {
pager_ckpt_begin $p1
}
}
} {}
do_test pager-4.5.$i.3 {
set res {}
for {set j 2} {$j<=20} {incr j} {
set gx [page_get $p1 $j]
set value [page_read $gx]
page_unref $gx
set shouldbe "Page-$j v$i"
if {$value!=$shouldbe} {
lappend res $value $shouldbe
}
}
set res
} {}
do_test pager-4.5.$i.4 {
pager_rollback $p1
set res {}
for {set j 2} {$j<=20} {incr j} {
set gx [page_get $p1 $j]
set value [page_read $gx]
page_unref $gx
set shouldbe "Page-$j v[expr {$i-1}]"
if {$value!=$shouldbe} {
lappend res $value $shouldbe
}
}
set res
} {}
do_test pager-4.5.$i.5 {
page_write $g1 "Page-1 v$i"
lrange [pager_stats $p1] 8 9
} {state 2}
do_test pager-4.5.$i.6 {
for {set j 2} {$j<=20} {incr j} {
set gx [page_get $p1 $j]
page_write $gx "Page-$j v$i"
page_unref $gx
if {$j==$i} {
pager_ckpt_begin $p1
}
}
} {}
do_test pager-4.5.$i.7 {
pager_ckpt_rollback $p1
for {set j 2} {$j<=20} {incr j} {
set gx [page_get $p1 $j]
set value [page_read $gx]
page_unref $gx
if {$j<=$i || $i==1} {
set shouldbe "Page-$j v$i"
} else {
set shouldbe "Page-$j v[expr {$i-1}]"
}
if {$value!=$shouldbe} {
lappend res $value $shouldbe
}
}
set res
} {}
do_test pager-4.5.$i.8 {
for {set j 2} {$j<=20} {incr j} {
set gx [page_get $p1 $j]
page_write $gx "Page-$j v$i"
page_unref $gx
if {$j==$i} {
pager_ckpt_begin $p1
}
}
} {}
do_test pager-4.5.$i.9 {
pager_ckpt_commit $p1
for {set j 2} {$j<=20} {incr j} {
set gx [page_get $p1 $j]
set value [page_read $gx]
page_unref $gx
set shouldbe "Page-$j v$i"
if {$value!=$shouldbe} {
lappend res $value $shouldbe
}
}
set res
} {}
do_test pager-4.5.$i.10 {
pager_commit $p1
lrange [pager_stats $p1] 8 9
} {state 1}
}
do_test pager-4.99 {
pager_close $::p1
} {}
file delete -force ptf1.db
} ;# end if( not mem: and has pager_open command ); } ;# end if( not mem: and has pager_open command );