1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-08 14:02:16 +03:00

Add read-transactions to the btree and vdbe. The compiler doesn't invoke

them yet. (CVS 1502)

FossilOrigin-Name: 6b43633a96c674a5d470578ef80ebf2227da0682
This commit is contained in:
danielk1977
2004-05-31 10:01:34 +00:00
parent 33752f8acf
commit ee5741ea78
9 changed files with 98 additions and 75 deletions

View File

@@ -9,7 +9,7 @@
** May you share freely, never taking more than you give.
**
*************************************************************************
** $Id: btree.c,v 1.153 2004/05/31 08:26:49 danielk1977 Exp $
** $Id: btree.c,v 1.154 2004/05/31 10:01:35 danielk1977 Exp $
**
** This file implements a external (disk-based) database using BTrees.
** For a detailed discussion of BTrees, refer to
@@ -316,6 +316,13 @@ struct Btree {
};
typedef Btree Bt;
/*
** Btree.inTrans may take one of the following values.
*/
#define TRANS_NONE 0
#define TRANS_READ 1
#define TRANS_WRITE 2
/*
** An instance of the following structure is used to hold information
** about a cell. The parseCellPtr() function fills in this structure
@@ -1142,10 +1149,9 @@ page1_init_failed:
** If there is a transaction in progress, this routine is a no-op.
*/
static void unlockBtreeIfUnused(Btree *pBt){
if( pBt->inTrans==0 && pBt->pCursor==0 && pBt->pPage1!=0 ){
if( pBt->inTrans==TRANS_NONE && pBt->pCursor==0 && pBt->pPage1!=0 ){
releasePage(pBt->pPage1);
pBt->pPage1 = 0;
pBt->inTrans = 0;
pBt->inStmt = 0;
}
}
@@ -1179,11 +1185,13 @@ static int newDatabase(Btree *pBt){
}
/*
** Attempt to start a new transaction.
** Attempt to start a new transaction. A write-transaction
** is started if the second argument is true, otherwise a read-
** transaction.
**
** A transaction must be started before attempting any changes
** to the database. None of the following routines will work
** unless a transaction is started first:
** A write-transaction must be started before attempting any
** changes to the database. None of the following routines
** will work unless a transaction is started first:
**
** sqlite3BtreeCreateTable()
** sqlite3BtreeCreateIndex()
@@ -1193,23 +1201,35 @@ static int newDatabase(Btree *pBt){
** sqlite3BtreeDelete()
** sqlite3BtreeUpdateMeta()
*/
int sqlite3BtreeBeginTrans(Btree *pBt){
int rc;
if( pBt->inTrans ) return SQLITE_ERROR;
if( pBt->readOnly ) return SQLITE_READONLY;
int sqlite3BtreeBeginTrans(Btree *pBt, int wrflag){
int rc = SQLITE_OK;
/* If the btree is already in a write-transaction, or it
** is already in a read-transaction and a read-transaction
** is requested, this is a no-op.
*/
if( pBt->inTrans==TRANS_WRITE ||
(pBt->inTrans==TRANS_READ && !wrflag) ){
return SQLITE_OK;
}
if( pBt->readOnly && wrflag ){
return SQLITE_READONLY;
}
if( pBt->pPage1==0 ){
rc = lockBtree(pBt);
if( rc!=SQLITE_OK ){
return rc;
}
if( rc==SQLITE_OK && wrflag ){
rc = sqlite3pager_begin(pBt->pPage1->aData);
if( rc==SQLITE_OK ){
rc = newDatabase(pBt);
}
}
rc = sqlite3pager_begin(pBt->pPage1->aData);
if( rc==SQLITE_OK ){
rc = newDatabase(pBt);
}
if( rc==SQLITE_OK ){
pBt->inTrans = 1;
pBt->inStmt = 0;
pBt->inTrans = (wrflag?TRANS_WRITE:TRANS_READ);
if( wrflag ) pBt->inStmt = 0;
}else{
unlockBtreeIfUnused(pBt);
}
@@ -1223,9 +1243,11 @@ int sqlite3BtreeBeginTrans(Btree *pBt){
** are no active cursors, it also releases the read lock.
*/
int sqlite3BtreeCommit(Btree *pBt){
int rc;
rc = pBt->readOnly ? SQLITE_OK : sqlite3pager_commit(pBt->pPager);
pBt->inTrans = 0;
int rc = SQLITE_OK;
if( pBt->inTrans==TRANS_WRITE ){
rc = sqlite3pager_commit(pBt->pPager);
}
pBt->inTrans = TRANS_NONE;
pBt->inStmt = 0;
unlockBtreeIfUnused(pBt);
return rc;
@@ -1278,12 +1300,7 @@ void sqlite3BtreeCursorList(Btree *pBt){
int sqlite3BtreeRollback(Btree *pBt){
int rc;
MemPage *pPage1;
if( pBt->inTrans==0 ) return SQLITE_OK;
pBt->inTrans = 0;
pBt->inStmt = 0;
if( pBt->readOnly ){
rc = SQLITE_OK;
}else{
if( pBt->inTrans==TRANS_WRITE ){
rc = sqlite3pager_rollback(pBt->pPager);
/* The rollback may have destroyed the pPage1->aData value. So
** call getPage() on page 1 again to make sure pPage1->aData is
@@ -1291,8 +1308,10 @@ int sqlite3BtreeRollback(Btree *pBt){
if( getPage(pBt, 1, &pPage1)==SQLITE_OK ){
releasePage(pPage1);
}
invalidateCursors(pBt);
}
invalidateCursors(pBt);
pBt->inTrans = TRANS_NONE;
pBt->inStmt = 0;
unlockBtreeIfUnused(pBt);
return rc;
}
@@ -1314,7 +1333,7 @@ int sqlite3BtreeRollback(Btree *pBt){
*/
int sqlite3BtreeBeginStmt(Btree *pBt){
int rc;
if( !pBt->inTrans || pBt->inStmt ){
if( (pBt->inTrans!=TRANS_WRITE) || pBt->inStmt ){
return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR;
}
rc = pBt->readOnly ? SQLITE_OK : sqlite3pager_stmt_begin(pBt->pPager);
@@ -3360,7 +3379,7 @@ int sqlite3BtreeInsert(
if( pCur->status ){
return pCur->status; /* A rollback destroyed this cursor */
}
if( !pBt->inTrans ){
if( pBt->inTrans!=TRANS_WRITE ){
/* Must start a transaction before doing an insert */
return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR;
}
@@ -3427,7 +3446,7 @@ int sqlite3BtreeDelete(BtCursor *pCur){
if( pCur->status ){
return pCur->status; /* A rollback destroyed this cursor */
}
if( !pBt->inTrans ){
if( pBt->inTrans!=TRANS_WRITE ){
/* Must start a transaction before doing a delete */
return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR;
}
@@ -3508,7 +3527,7 @@ int sqlite3BtreeCreateTable(Btree *pBt, int *piTable, int flags){
MemPage *pRoot;
Pgno pgnoRoot;
int rc;
if( !pBt->inTrans ){
if( pBt->inTrans!=TRANS_WRITE ){
/* Must start a transaction first */
return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR;
}
@@ -3577,7 +3596,7 @@ static int clearDatabasePage(
int sqlite3BtreeClearTable(Btree *pBt, int iTable){
int rc;
BtCursor *pCur;
if( !pBt->inTrans ){
if( pBt->inTrans!=TRANS_WRITE ){
return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR;
}
for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){
@@ -3605,7 +3624,7 @@ int sqlite3BtreeDropTable(Btree *pBt, int iTable){
int rc;
MemPage *pPage;
BtCursor *pCur;
if( !pBt->inTrans ){
if( pBt->inTrans!=TRANS_WRITE ){
return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR;
}
for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){
@@ -3657,7 +3676,7 @@ int sqlite3BtreeUpdateMeta(Btree *pBt, int idx, u32 iMeta){
unsigned char *pP1;
int rc;
assert( idx>=1 && idx<=15 );
if( !pBt->inTrans ){
if( pBt->inTrans!=TRANS_WRITE ){
return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR;
}
assert( pBt->pPage1!=0 );
@@ -4153,7 +4172,9 @@ int sqlite3BtreeCopyFile(Btree *pBtTo, Btree *pBtFrom){
int rc = SQLITE_OK;
Pgno i, nPage, nToPage;
if( !pBtTo->inTrans || !pBtFrom->inTrans ) return SQLITE_ERROR;
if( pBtTo->inTrans!=TRANS_WRITE || pBtFrom->inTrans!=TRANS_WRITE ){
return SQLITE_ERROR;
}
if( pBtTo->pCursor ) return SQLITE_BUSY;
memcpy(pBtTo->pPage1->aData, pBtFrom->pPage1->aData, pBtFrom->usableSize);
rc = sqlite3pager_overwrite(pBtTo->pPager, 1, pBtFrom->pPage1->aData);
@@ -4188,7 +4209,7 @@ int sqlite3BtreeCopyFile(Btree *pBtTo, Btree *pBtFrom){
** Return non-zero if a transaction is active.
*/
int sqlite3BtreeIsInTrans(Btree *pBt){
return (pBt && pBt->inTrans);
return (pBt && (pBt->inTrans==TRANS_WRITE));
}
/*