1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-07-30 19:03:16 +03:00

Add infrastructure to suport multiple btree implementations (CVS 894)

FossilOrigin-Name: 79b3aed2a74a67cbad631c4e2e4a43469d80c162
This commit is contained in:
paul
2003-04-01 21:16:41 +00:00
parent 738a68b250
commit b95a8864c9
4 changed files with 229 additions and 81 deletions

View File

@ -1,5 +1,5 @@
C Minor\sfollow-on\schanges\sto\sthe\srecent\sATTACH\spatch.\s(CVS\s893) C Add\sinfrastructure\sto\ssuport\smultiple\sbtree\simplementations\s(CVS\s894)
D 2003-03-31T13:36:09 D 2003-04-01T21:16:42
F Makefile.in 3c4ba24253e61c954d67adbbb4245e7117c5357e F Makefile.in 3c4ba24253e61c954d67adbbb4245e7117c5357e
F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906 F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
@ -20,8 +20,8 @@ F spec.template 238f7db425a78dc1bb7682e56e3834c7270a3f5e
F sqlite.1 83f4a9d37bdf2b7ef079a82d54eaf2e3509ee6ea F sqlite.1 83f4a9d37bdf2b7ef079a82d54eaf2e3509ee6ea
F sqlite.pc.in 30552343140c53304c2a658c080fbe810cd09ca2 F sqlite.pc.in 30552343140c53304c2a658c080fbe810cd09ca2
F src/auth.c f37bfc9451b8c1fa52f34adff474560018892729 F src/auth.c f37bfc9451b8c1fa52f34adff474560018892729
F src/btree.c dba4d12945228dd7e94de7da0e1d8638b70d99f2 F src/btree.c 7eae5413a7f957bb0733bcab6fab31c6943c51d2
F src/btree.h 8209bfadf5845d4fdaa60f471bb360f894cd4095 F src/btree.h 024d2dd21310c202d648c6244dec885e48efa9ad
F src/build.c 81d31f2e63d51683ee653df6399acc3c3a2e3672 F src/build.c 81d31f2e63d51683ee653df6399acc3c3a2e3672
F src/delete.c 58d698779a6b7f819718ecd45b310a9de8537088 F src/delete.c 58d698779a6b7f819718ecd45b310a9de8537088
F src/encode.c faf03741efe921755ec371cf4a6984536de00042 F src/encode.c faf03741efe921755ec371cf4a6984536de00042
@ -155,7 +155,7 @@ F www/speed.tcl cb4c10a722614aea76d2c51f32ee43400d5951be
F www/sqlite.tcl ae3dcfb077e53833b59d4fcc94d8a12c50a44098 F www/sqlite.tcl ae3dcfb077e53833b59d4fcc94d8a12c50a44098
F www/tclsqlite.tcl 1db15abeb446aad0caf0b95b8b9579720e4ea331 F www/tclsqlite.tcl 1db15abeb446aad0caf0b95b8b9579720e4ea331
F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218 F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218
P e80afe75b33d4eacb40ef6128cf688f7c3253984 P 11378c5bf988412f8564cdc0314fc241793b292e
R 8452f551322a2a47e2174b852766e085 R cc8e4c3807eb9ac6929fb512790ca871
U drh U paul
Z 7162b736d28f6cc7cea678e58590971b Z 048b3196e99f227ca8551c2b49ca1411

View File

@ -1 +1 @@
11378c5bf988412f8564cdc0314fc241793b292e 79b3aed2a74a67cbad631c4e2e4a43469d80c162

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.85 2003/03/30 18:41:22 drh Exp $ ** $Id: btree.c,v 1.86 2003/04/01 21:16:42 paul 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
@ -49,11 +49,18 @@
** BTree begins on page 2 of the file. (Pages are numbered beginning with ** BTree begins on page 2 of the file. (Pages are numbered beginning with
** 1, not 0.) Thus a minimum database contains 2 pages. ** 1, not 0.) Thus a minimum database contains 2 pages.
*/ */
/* We don't want the btree function macros */
#define SQLITE_NO_BTREE_DEFS
#include "sqliteInt.h" #include "sqliteInt.h"
#include "pager.h" #include "pager.h"
#include "btree.h" #include "btree.h"
#include <assert.h> #include <assert.h>
/* Forward declarations */
static BtOps sqliteBtreeOps;
static BtCursorOps sqliteBtreeCursorOps;
/* /*
** Macros used for byteswapping. B is a pointer to the Btree ** Macros used for byteswapping. B is a pointer to the Btree
** structure. This is needed to access the Btree.needSwab boolean ** structure. This is needed to access the Btree.needSwab boolean
@ -340,6 +347,7 @@ struct MemPage {
** Everything we need to know about an open database ** Everything we need to know about an open database
*/ */
struct Btree { struct Btree {
BtOps *pOps; /* Function table */
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 */
@ -356,6 +364,7 @@ typedef Btree Bt;
** MemPage.apCell[] of the entry. ** MemPage.apCell[] of the entry.
*/ */
struct BtCursor { struct BtCursor {
BtCursorOps *pOps; /* Function table */
Btree *pBt; /* The Btree to which this cursor belongs */ Btree *pBt; /* The Btree to which this cursor belongs */
BtCursor *pNext, *pPrev; /* Forms a linked list of all cursors */ BtCursor *pNext, *pPrev; /* Forms a linked list of all cursors */
BtCursor *pShared; /* Loop of cursors with the same root page */ BtCursor *pShared; /* Loop of cursors with the same root page */
@ -375,6 +384,9 @@ struct BtCursor {
#define SKIP_PREV 2 /* The next sqliteBtreePrevious() is a no-op */ #define SKIP_PREV 2 /* The next sqliteBtreePrevious() is a no-op */
#define SKIP_INVALID 3 /* Calls to Next() and Previous() are invalid */ #define SKIP_INVALID 3 /* Calls to Next() and Previous() are invalid */
/* Forward declarations */
static int sqliteBtreeCloseCursor(BtCursor *pCur);
/* /*
** Routines for byte swapping. ** Routines for byte swapping.
*/ */
@ -709,6 +721,7 @@ int sqliteBtreeOpen(
pBt->pCursor = 0; pBt->pCursor = 0;
pBt->page1 = 0; pBt->page1 = 0;
pBt->readOnly = sqlitepager_isreadonly(pBt->pPager); pBt->readOnly = sqlitepager_isreadonly(pBt->pPager);
pBt->pOps = &sqliteBtreeOps;
*ppBtree = pBt; *ppBtree = pBt;
return SQLITE_OK; return SQLITE_OK;
} }
@ -716,7 +729,7 @@ int sqliteBtreeOpen(
/* /*
** Close an open database and invalidate all cursors. ** Close an open database and invalidate all cursors.
*/ */
int sqliteBtreeClose(Btree *pBt){ static int sqliteBtreeClose(Btree *pBt){
while( pBt->pCursor ){ while( pBt->pCursor ){
sqliteBtreeCloseCursor(pBt->pCursor); sqliteBtreeCloseCursor(pBt->pCursor);
} }
@ -740,7 +753,7 @@ int sqliteBtreeClose(Btree *pBt){
** Synchronous is on by default so database corruption is not ** Synchronous is on by default so database corruption is not
** normally a worry. ** normally a worry.
*/ */
int sqliteBtreeSetCacheSize(Btree *pBt, int mxPage){ static int sqliteBtreeSetCacheSize(Btree *pBt, int mxPage){
sqlitepager_set_cachesize(pBt->pPager, mxPage); sqlitepager_set_cachesize(pBt->pPager, mxPage);
return SQLITE_OK; return SQLITE_OK;
} }
@ -753,7 +766,7 @@ int sqliteBtreeSetCacheSize(Btree *pBt, int mxPage){
** is a very low but non-zero probability of damage. Level 3 reduces the ** is a very low but non-zero probability of damage. Level 3 reduces the
** probability of damage to near zero but with a write performance reduction. ** probability of damage to near zero but with a write performance reduction.
*/ */
int sqliteBtreeSetSafetyLevel(Btree *pBt, int level){ static int sqliteBtreeSetSafetyLevel(Btree *pBt, int level){
sqlitepager_set_safety_level(pBt->pPager, level); sqlitepager_set_safety_level(pBt->pPager, level);
return SQLITE_OK; return SQLITE_OK;
} }
@ -860,7 +873,7 @@ static int newDatabase(Btree *pBt){
** sqliteBtreeDelete() ** sqliteBtreeDelete()
** sqliteBtreeUpdateMeta() ** sqliteBtreeUpdateMeta()
*/ */
int sqliteBtreeBeginTrans(Btree *pBt){ static int sqliteBtreeBeginTrans(Btree *pBt){
int rc; int rc;
if( pBt->inTrans ) return SQLITE_ERROR; if( pBt->inTrans ) return SQLITE_ERROR;
if( pBt->readOnly ) return SQLITE_READONLY; if( pBt->readOnly ) return SQLITE_READONLY;
@ -889,7 +902,7 @@ int sqliteBtreeBeginTrans(Btree *pBt){
** This will release the write lock on the database file. If there ** This will release the write lock on the database file. If there
** are no active cursors, it also releases the read lock. ** are no active cursors, it also releases the read lock.
*/ */
int sqliteBtreeCommit(Btree *pBt){ static int sqliteBtreeCommit(Btree *pBt){
int rc; int rc;
rc = pBt->readOnly ? SQLITE_OK : sqlitepager_commit(pBt->pPager); rc = pBt->readOnly ? SQLITE_OK : sqlitepager_commit(pBt->pPager);
pBt->inTrans = 0; pBt->inTrans = 0;
@ -907,7 +920,7 @@ int sqliteBtreeCommit(Btree *pBt){
** This will release the write lock on the database file. If there ** This will release the write lock on the database file. If there
** are no active cursors, it also releases the read lock. ** are no active cursors, it also releases the read lock.
*/ */
int sqliteBtreeRollback(Btree *pBt){ static int sqliteBtreeRollback(Btree *pBt){
int rc; int rc;
BtCursor *pCur; BtCursor *pCur;
if( pBt->inTrans==0 ) return SQLITE_OK; if( pBt->inTrans==0 ) return SQLITE_OK;
@ -934,7 +947,7 @@ int sqliteBtreeRollback(Btree *pBt){
** Only one checkpoint may be active at a time. It is an error to try ** 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. ** to start a new checkpoint if another checkpoint is already active.
*/ */
int sqliteBtreeBeginCkpt(Btree *pBt){ static int sqliteBtreeBeginCkpt(Btree *pBt){
int rc; int rc;
if( !pBt->inTrans || pBt->inCkpt ){ if( !pBt->inTrans || pBt->inCkpt ){
return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR;
@ -949,7 +962,7 @@ int sqliteBtreeBeginCkpt(Btree *pBt){
** Commit a checkpoint to transaction currently in progress. If no ** Commit a checkpoint to transaction currently in progress. If no
** checkpoint is active, this is a no-op. ** checkpoint is active, this is a no-op.
*/ */
int sqliteBtreeCommitCkpt(Btree *pBt){ static int sqliteBtreeCommitCkpt(Btree *pBt){
int rc; int rc;
if( pBt->inCkpt && !pBt->readOnly ){ if( pBt->inCkpt && !pBt->readOnly ){
rc = sqlitepager_ckpt_commit(pBt->pPager); rc = sqlitepager_ckpt_commit(pBt->pPager);
@ -968,7 +981,7 @@ int sqliteBtreeCommitCkpt(Btree *pBt){
** to use a cursor that was open at the beginning of this operation ** to use a cursor that was open at the beginning of this operation
** will result in an error. ** will result in an error.
*/ */
int sqliteBtreeRollbackCkpt(Btree *pBt){ static int sqliteBtreeRollbackCkpt(Btree *pBt){
int rc; int rc;
BtCursor *pCur; BtCursor *pCur;
if( pBt->inCkpt==0 || pBt->readOnly ) return SQLITE_OK; if( pBt->inCkpt==0 || pBt->readOnly ) return SQLITE_OK;
@ -1019,7 +1032,7 @@ int sqliteBtreeRollbackCkpt(Btree *pBt){
** root page of a b-tree. If it is not, then the cursor acquired ** root page of a b-tree. If it is not, then the cursor acquired
** will not work correctly. ** will not work correctly.
*/ */
int sqliteBtreeCursor(Btree *pBt, int iTable, int wrFlag, BtCursor **ppCur){ static int sqliteBtreeCursor(Btree *pBt, int iTable, int wrFlag, BtCursor **ppCur){
int rc; int rc;
BtCursor *pCur, *pRing; BtCursor *pCur, *pRing;
@ -1044,6 +1057,7 @@ int sqliteBtreeCursor(Btree *pBt, int iTable, int wrFlag, BtCursor **ppCur){
if( rc!=SQLITE_OK ){ if( rc!=SQLITE_OK ){
goto create_cursor_exception; goto create_cursor_exception;
} }
pCur->pOps = &sqliteBtreeCursorOps;
pCur->pBt = pBt; pCur->pBt = pBt;
pCur->wrFlag = wrFlag; pCur->wrFlag = wrFlag;
pCur->idx = 0; pCur->idx = 0;
@ -1079,7 +1093,7 @@ create_cursor_exception:
** Close a cursor. The read lock on the database file is released ** Close a cursor. The read lock on the database file is released
** when the last cursor is closed. ** when the last cursor is closed.
*/ */
int sqliteBtreeCloseCursor(BtCursor *pCur){ static int sqliteBtreeCloseCursor(BtCursor *pCur){
Btree *pBt = pCur->pBt; Btree *pBt = pCur->pBt;
if( pCur->pPrev ){ if( pCur->pPrev ){
pCur->pPrev->pNext = pCur->pNext; pCur->pPrev->pNext = pCur->pNext;
@ -1132,7 +1146,7 @@ static void releaseTempCursor(BtCursor *pCur){
** pointing to an entry (which can happen, for example, if ** pointing to an entry (which can happen, for example, if
** the database is empty) then *pSize is set to 0. ** the database is empty) then *pSize is set to 0.
*/ */
int sqliteBtreeKeySize(BtCursor *pCur, int *pSize){ static int sqliteBtreeKeySize(BtCursor *pCur, int *pSize){
Cell *pCell; Cell *pCell;
MemPage *pPage; MemPage *pPage;
@ -1221,7 +1235,7 @@ static int getPayload(BtCursor *pCur, int offset, int amt, char *zBuf){
** is raised. The change was made in an effort to boost performance ** is raised. The change was made in an effort to boost performance
** by eliminating unneeded tests. ** by eliminating unneeded tests.
*/ */
int sqliteBtreeKey(BtCursor *pCur, int offset, int amt, char *zBuf){ static int sqliteBtreeKey(BtCursor *pCur, int offset, int amt, char *zBuf){
MemPage *pPage; MemPage *pPage;
assert( amt>=0 ); assert( amt>=0 );
@ -1243,7 +1257,7 @@ int sqliteBtreeKey(BtCursor *pCur, int offset, int amt, char *zBuf){
** pointing to an entry (which can happen, for example, if ** pointing to an entry (which can happen, for example, if
** the database is empty) then *pSize is set to 0. ** the database is empty) then *pSize is set to 0.
*/ */
int sqliteBtreeDataSize(BtCursor *pCur, int *pSize){ static int sqliteBtreeDataSize(BtCursor *pCur, int *pSize){
Cell *pCell; Cell *pCell;
MemPage *pPage; MemPage *pPage;
@ -1266,7 +1280,7 @@ int sqliteBtreeDataSize(BtCursor *pCur, int *pSize){
** amount requested if there are not enough bytes in the data ** amount requested if there are not enough bytes in the data
** to satisfy the request. ** to satisfy the request.
*/ */
int sqliteBtreeData(BtCursor *pCur, int offset, int amt, char *zBuf){ static int sqliteBtreeData(BtCursor *pCur, int offset, int amt, char *zBuf){
Cell *pCell; Cell *pCell;
MemPage *pPage; MemPage *pPage;
@ -1304,7 +1318,7 @@ int sqliteBtreeData(BtCursor *pCur, int offset, int amt, char *zBuf){
** keys must be exactly the same length. (The length of the pCur key ** keys must be exactly the same length. (The length of the pCur key
** is the actual key length minus nIgnore bytes.) ** is the actual key length minus nIgnore bytes.)
*/ */
int sqliteBtreeKeyCompare( static int sqliteBtreeKeyCompare(
BtCursor *pCur, /* Pointer to entry to compare against */ BtCursor *pCur, /* Pointer to entry to compare against */
const void *pKey, /* Key to compare against entry that pCur points to */ const void *pKey, /* Key to compare against entry that pCur points to */
int nKey, /* Number of bytes in pKey */ int nKey, /* Number of bytes in pKey */
@ -1503,7 +1517,7 @@ static int moveToRightmost(BtCursor *pCur){
** on success. Set *pRes to 0 if the cursor actually points to something ** on success. Set *pRes to 0 if the cursor actually points to something
** or set *pRes to 1 if the table is empty. ** or set *pRes to 1 if the table is empty.
*/ */
int sqliteBtreeFirst(BtCursor *pCur, int *pRes){ static int sqliteBtreeFirst(BtCursor *pCur, int *pRes){
int rc; int rc;
if( pCur->pPage==0 ) return SQLITE_ABORT; if( pCur->pPage==0 ) return SQLITE_ABORT;
rc = moveToRoot(pCur); rc = moveToRoot(pCur);
@ -1522,7 +1536,7 @@ int sqliteBtreeFirst(BtCursor *pCur, int *pRes){
** on success. Set *pRes to 0 if the cursor actually points to something ** on success. Set *pRes to 0 if the cursor actually points to something
** or set *pRes to 1 if the table is empty. ** or set *pRes to 1 if the table is empty.
*/ */
int sqliteBtreeLast(BtCursor *pCur, int *pRes){ static int sqliteBtreeLast(BtCursor *pCur, int *pRes){
int rc; int rc;
if( pCur->pPage==0 ) return SQLITE_ABORT; if( pCur->pPage==0 ) return SQLITE_ABORT;
rc = moveToRoot(pCur); rc = moveToRoot(pCur);
@ -1561,7 +1575,7 @@ int sqliteBtreeLast(BtCursor *pCur, int *pRes){
** *pRes>0 The cursor is left pointing at an entry that ** *pRes>0 The cursor is left pointing at an entry that
** is larger than pKey. ** is larger than pKey.
*/ */
int sqliteBtreeMoveto(BtCursor *pCur, const void *pKey, int nKey, int *pRes){ static int sqliteBtreeMoveto(BtCursor *pCur, const void *pKey, int nKey, int *pRes){
int rc; int rc;
if( pCur->pPage==0 ) return SQLITE_ABORT; if( pCur->pPage==0 ) return SQLITE_ABORT;
pCur->eSkip = SKIP_NONE; pCur->eSkip = SKIP_NONE;
@ -1614,7 +1628,7 @@ int sqliteBtreeMoveto(BtCursor *pCur, const void *pKey, int nKey, int *pRes){
** was already pointing to the last entry in the database before ** was already pointing to the last entry in the database before
** this routine was called, then set *pRes=1. ** this routine was called, then set *pRes=1.
*/ */
int sqliteBtreeNext(BtCursor *pCur, int *pRes){ static int sqliteBtreeNext(BtCursor *pCur, int *pRes){
int rc; int rc;
MemPage *pPage = pCur->pPage; MemPage *pPage = pCur->pPage;
assert( pRes!=0 ); assert( pRes!=0 );
@ -1669,7 +1683,7 @@ int sqliteBtreeNext(BtCursor *pCur, int *pRes){
** was already pointing to the first entry in the database before ** was already pointing to the first entry in the database before
** this routine was called, then set *pRes=1. ** this routine was called, then set *pRes=1.
*/ */
int sqliteBtreePrevious(BtCursor *pCur, int *pRes){ static int sqliteBtreePrevious(BtCursor *pCur, int *pRes){
int rc; int rc;
Pgno pgno; Pgno pgno;
MemPage *pPage; MemPage *pPage;
@ -2595,7 +2609,7 @@ static int checkReadLocks(BtCursor *pCur){
** define what database the record should be inserted into. The cursor ** define what database the record should be inserted into. The cursor
** is left pointing at the new record. ** is left pointing at the new record.
*/ */
int sqliteBtreeInsert( static int sqliteBtreeInsert(
BtCursor *pCur, /* Insert data into the table of this cursor */ BtCursor *pCur, /* Insert data into the table of this cursor */
const void *pKey, int nKey, /* The key of the new record */ const void *pKey, int nKey, /* The key of the new record */
const void *pData, int nData /* The data of the new record */ const void *pData, int nData /* The data of the new record */
@ -2663,7 +2677,7 @@ int sqliteBtreeInsert(
** sqliteBtreePrevious() will always leave the cursor pointing at the ** sqliteBtreePrevious() will always leave the cursor pointing at the
** entry immediately before the one that was deleted. ** entry immediately before the one that was deleted.
*/ */
int sqliteBtreeDelete(BtCursor *pCur){ static int sqliteBtreeDelete(BtCursor *pCur){
MemPage *pPage = pCur->pPage; MemPage *pPage = pCur->pPage;
Cell *pCell; Cell *pCell;
int rc; int rc;
@ -2750,7 +2764,7 @@ int sqliteBtreeDelete(BtCursor *pCur){
** are restricted to having a 4-byte integer key and arbitrary data and ** are restricted to having a 4-byte integer key and arbitrary data and
** BTree indices are restricted to having an arbitrary key and no data. ** BTree indices are restricted to having an arbitrary key and no data.
*/ */
int sqliteBtreeCreateTable(Btree *pBt, int *piTable){ static int sqliteBtreeCreateTable(Btree *pBt, int *piTable){
MemPage *pRoot; MemPage *pRoot;
Pgno pgnoRoot; Pgno pgnoRoot;
int rc; int rc;
@ -2779,7 +2793,7 @@ int sqliteBtreeCreateTable(Btree *pBt, int *piTable){
** are restricted to having a 4-byte integer key and arbitrary data and ** are restricted to having a 4-byte integer key and arbitrary data and
** BTree indices are restricted to having an arbitrary key and no data. ** BTree indices are restricted to having an arbitrary key and no data.
*/ */
int sqliteBtreeCreateIndex(Btree *pBt, int *piIndex){ static int sqliteBtreeCreateIndex(Btree *pBt, int *piIndex){
return sqliteBtreeCreateTable(pBt, piIndex); return sqliteBtreeCreateTable(pBt, piIndex);
} }
@ -2826,7 +2840,7 @@ static int clearDatabasePage(Btree *pBt, Pgno pgno, int freePageFlag){
/* /*
** Delete all information from a single table in the database. ** Delete all information from a single table in the database.
*/ */
int sqliteBtreeClearTable(Btree *pBt, int iTable){ static int sqliteBtreeClearTable(Btree *pBt, int iTable){
int rc; int rc;
BtCursor *pCur; BtCursor *pCur;
if( !pBt->inTrans ){ if( !pBt->inTrans ){
@ -2850,7 +2864,7 @@ int sqliteBtreeClearTable(Btree *pBt, int iTable){
** the freelist. Except, the root of the principle table (the one on ** the freelist. Except, the root of the principle table (the one on
** page 2) is never added to the freelist. ** page 2) is never added to the freelist.
*/ */
int sqliteBtreeDropTable(Btree *pBt, int iTable){ static int sqliteBtreeDropTable(Btree *pBt, int iTable){
int rc; int rc;
MemPage *pPage; MemPage *pPage;
BtCursor *pCur; BtCursor *pCur;
@ -2977,7 +2991,7 @@ static int copyDatabasePage(
/* /*
** Read the meta-information out of a database file. ** Read the meta-information out of a database file.
*/ */
int sqliteBtreeGetMeta(Btree *pBt, int *aMeta){ static int sqliteBtreeGetMeta(Btree *pBt, int *aMeta){
PageOne *pP1; PageOne *pP1;
int rc; int rc;
int i; int i;
@ -2995,7 +3009,7 @@ int sqliteBtreeGetMeta(Btree *pBt, int *aMeta){
/* /*
** Write meta-information back into the database. ** Write meta-information back into the database.
*/ */
int sqliteBtreeUpdateMeta(Btree *pBt, int *aMeta){ static int sqliteBtreeUpdateMeta(Btree *pBt, int *aMeta){
PageOne *pP1; PageOne *pP1;
int rc, i; int rc, i;
if( !pBt->inTrans ){ if( !pBt->inTrans ){
@ -3021,7 +3035,7 @@ int sqliteBtreeUpdateMeta(Btree *pBt, int *aMeta){
** is used for debugging and testing only. ** is used for debugging and testing only.
*/ */
#ifdef SQLITE_TEST #ifdef SQLITE_TEST
int sqliteBtreePageDump(Btree *pBt, int pgno, int recursive){ static int sqliteBtreePageDump(Btree *pBt, int pgno, int recursive){
int rc; int rc;
MemPage *pPage; MemPage *pPage;
int i, j; int i, j;
@ -3108,7 +3122,7 @@ int sqliteBtreePageDump(Btree *pBt, int pgno, int recursive){
** **
** This routine is used for testing and debugging only. ** This routine is used for testing and debugging only.
*/ */
int sqliteBtreeCursorDump(BtCursor *pCur, int *aResult){ static int sqliteBtreeCursorDump(BtCursor *pCur, int *aResult){
int cnt, idx; int cnt, idx;
MemPage *pPage = pCur->pPage; MemPage *pPage = pCur->pPage;
Btree *pBt = pCur->pBt; Btree *pBt = pCur->pBt;
@ -3140,7 +3154,7 @@ int sqliteBtreeCursorDump(BtCursor *pCur, int *aResult){
** Return the pager associated with a BTree. This routine is used for ** Return the pager associated with a BTree. This routine is used for
** testing and debugging only. ** testing and debugging only.
*/ */
Pager *sqliteBtreePager(Btree *pBt){ static Pager *sqliteBtreePager(Btree *pBt){
return pBt->pPager; return pBt->pPager;
} }
#endif #endif
@ -3480,3 +3494,47 @@ char *sqliteBtreeIntegrityCheck(Btree *pBt, int *aRoot, int nRoot){
sqliteFree(sCheck.anRef); sqliteFree(sCheck.anRef);
return sCheck.zErrMsg; return sCheck.zErrMsg;
} }
static BtOps sqliteBtreeOps = {
sqliteBtreeClose,
sqliteBtreeSetCacheSize,
sqliteBtreeSetSafetyLevel,
sqliteBtreeBeginTrans,
sqliteBtreeCommit,
sqliteBtreeRollback,
sqliteBtreeBeginCkpt,
sqliteBtreeCommitCkpt,
sqliteBtreeRollbackCkpt,
sqliteBtreeCreateTable,
sqliteBtreeCreateIndex,
sqliteBtreeDropTable,
sqliteBtreeClearTable,
sqliteBtreeCursor,
sqliteBtreeGetMeta,
sqliteBtreeUpdateMeta,
sqliteBtreeIntegrityCheck,
#ifdef SQLITE_TEST
sqliteBtreePageDump,
sqliteBtreePager
#endif
};
static BtCursorOps sqliteBtreeCursorOps = {
sqliteBtreeMoveto,
sqliteBtreeDelete,
sqliteBtreeInsert,
sqliteBtreeFirst,
sqliteBtreeLast,
sqliteBtreeNext,
sqliteBtreePrevious,
sqliteBtreeKeySize,
sqliteBtreeKey,
sqliteBtreeKeyCompare,
sqliteBtreeDataSize,
sqliteBtreeData,
sqliteBtreeCloseCursor,
#ifdef SQLITE_TEST
sqliteBtreeCursorDump,
#endif
};

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.28 2003/03/19 03:14:01 drh Exp $ ** @(#) $Id: btree.h,v 1.29 2003/04/01 21:16:43 paul Exp $
*/ */
#ifndef _BTREE_H_ #ifndef _BTREE_H_
#define _BTREE_H_ #define _BTREE_H_
@ -21,51 +21,141 @@
typedef struct Btree Btree; typedef struct Btree Btree;
typedef struct BtCursor BtCursor; typedef struct BtCursor BtCursor;
int sqliteBtreeOpen(const char *zFilename, int mode, int nPg, Btree **ppBtree); struct BtOps {
int sqliteBtreeClose(Btree*); int (*sqliteBtreeClose)(Btree*);
int sqliteBtreeSetCacheSize(Btree*, int); int (*sqliteBtreeSetCacheSize)(Btree*, int);
int sqliteBtreeSetSafetyLevel(Btree*, int); int (*sqliteBtreeSetSafetyLevel)(Btree*, int);
int sqliteBtreeBeginTrans(Btree*); int (*sqliteBtreeBeginTrans)(Btree*);
int sqliteBtreeCommit(Btree*); int (*sqliteBtreeCommit)(Btree*);
int sqliteBtreeRollback(Btree*); int (*sqliteBtreeRollback)(Btree*);
int sqliteBtreeBeginCkpt(Btree*); int (*sqliteBtreeBeginCkpt)(Btree*);
int sqliteBtreeCommitCkpt(Btree*); int (*sqliteBtreeCommitCkpt)(Btree*);
int sqliteBtreeRollbackCkpt(Btree*); int (*sqliteBtreeRollbackCkpt)(Btree*);
int sqliteBtreeCreateTable(Btree*, int*); int (*sqliteBtreeCreateTable)(Btree*, int*);
int sqliteBtreeCreateIndex(Btree*, int*); int (*sqliteBtreeCreateIndex)(Btree*, int*);
int sqliteBtreeDropTable(Btree*, int); int (*sqliteBtreeDropTable)(Btree*, int);
int sqliteBtreeClearTable(Btree*, int); int (*sqliteBtreeClearTable)(Btree*, int);
int sqliteBtreeCopyTable(Btree *pFrom, int iFrom, Btree *pTo, int iTo);
int sqliteBtreeCursor(Btree*, int iTable, int wrFlag, BtCursor **ppCur); int (*sqliteBtreeCursor)(Btree*, int iTable, int wrFlag, BtCursor **ppCur);
int sqliteBtreeMoveto(BtCursor*, const void *pKey, int nKey, int *pRes);
int sqliteBtreeDelete(BtCursor*);
int sqliteBtreeInsert(BtCursor*, const void *pKey, int nKey,
const void *pData, int nData);
int sqliteBtreeFirst(BtCursor*, int *pRes);
int sqliteBtreeLast(BtCursor*, int *pRes);
int sqliteBtreeNext(BtCursor*, int *pRes);
int sqliteBtreePrevious(BtCursor*, int *pRes);
int sqliteBtreeKeySize(BtCursor*, int *pSize);
int sqliteBtreeKey(BtCursor*, int offset, int amt, char *zBuf);
int sqliteBtreeKeyCompare(BtCursor*, const void *pKey, int nKey,
int nIgnore, int *pRes);
int sqliteBtreeDataSize(BtCursor*, int *pSize);
int sqliteBtreeData(BtCursor*, int offset, int amt, char *zBuf);
int sqliteBtreeCloseCursor(BtCursor*);
#define SQLITE_N_BTREE_META 10 int (*sqliteBtreeGetMeta)(Btree*, int*);
int sqliteBtreeGetMeta(Btree*, int*); int (*sqliteBtreeUpdateMeta)(Btree*, int*);
int sqliteBtreeUpdateMeta(Btree*, int*);
char *sqliteBtreeIntegrityCheck(Btree*, int*, int); char *(*sqliteBtreeIntegrityCheck)(Btree*, int*, int);
#ifdef SQLITE_TEST #ifdef SQLITE_TEST
int sqliteBtreePageDump(Btree*, int, int); int (*sqliteBtreePageDump)(Btree*, int, int);
int sqliteBtreeCursorDump(BtCursor*, int*); struct Pager * (*sqliteBtreePager)(Btree*);
struct Pager *sqliteBtreePager(Btree*); #endif
};
typedef struct BtOps BtOps;
struct BtCursorOps {
int (*sqliteBtreeMoveto)(BtCursor*, const void *pKey, int nKey, int *pRes);
int (*sqliteBtreeDelete)(BtCursor*);
int (*sqliteBtreeInsert)(BtCursor*, const void *pKey, int nKey,
const void *pData, int nData);
int (*sqliteBtreeFirst)(BtCursor*, int *pRes);
int (*sqliteBtreeLast)(BtCursor*, int *pRes);
int (*sqliteBtreeNext)(BtCursor*, int *pRes);
int (*sqliteBtreePrevious)(BtCursor*, int *pRes);
int (*sqliteBtreeKeySize)(BtCursor*, int *pSize);
int (*sqliteBtreeKey)(BtCursor*, int offset, int amt, char *zBuf);
int (*sqliteBtreeKeyCompare)(BtCursor*, const void *pKey, int nKey,
int nIgnore, int *pRes);
int (*sqliteBtreeDataSize)(BtCursor*, int *pSize);
int (*sqliteBtreeData)(BtCursor*, int offset, int amt, char *zBuf);
int (*sqliteBtreeCloseCursor)(BtCursor*);
#ifdef SQLITE_TEST
int (*sqliteBtreeCursorDump)(BtCursor*, int*);
#endif
};
typedef struct BtCursorOps BtCursorOps;
#define SQLITE_N_BTREE_META 10
int sqliteBtreeOpen(const char *zFilename, int mode, int nPg, Btree **ppBtree);
#if !defined(SQLITE_NO_BTREE_DEFS)
#define btOps(pBt) (*((BtOps **)(pBt)))
#define btCOps(pCur) (*((BtCursorOps **)(pCur)))
#define sqliteBtreeClose(pBt)\
(btOps(pBt)->sqliteBtreeClose(pBt))
#define sqliteBtreeSetCacheSize(pBt, sz)\
(btOps(pBt)->sqliteBtreeSetCacheSize(pBt, sz))
#define sqliteBtreeSetSafetyLevel(pBt, sl)\
(btOps(pBt)->sqliteBtreeSetSafetyLevel(pBt, sl))
#define sqliteBtreeBeginTrans(pBt)\
(btOps(pBt)->sqliteBtreeBeginTrans(pBt))
#define sqliteBtreeCommit(pBt)\
(btOps(pBt)->sqliteBtreeCommit(pBt))
#define sqliteBtreeRollback(pBt)\
(btOps(pBt)->sqliteBtreeRollback(pBt))
#define sqliteBtreeBeginCkpt(pBt)\
(btOps(pBt)->sqliteBtreeBeginCkpt(pBt))
#define sqliteBtreeCommitCkpt(pBt)\
(btOps(pBt)->sqliteBtreeCommitCkpt(pBt))
#define sqliteBtreeRollbackCkpt(pBt)\
(btOps(pBt)->sqliteBtreeRollbackCkpt(pBt))
#define sqliteBtreeCreateTable(pBt, piTable)\
(btOps(pBt)->sqliteBtreeCreateTable(pBt, piTable))
#define sqliteBtreeCreateIndex(pBt, piIndex)\
(btOps(pBt)->sqliteBtreeCreateIndex(pBt, piIndex))
#define sqliteBtreeDropTable(pBt, iTable)\
(btOps(pBt)->sqliteBtreeDropTable(pBt, iTable))
#define sqliteBtreeClearTable(pBt, iTable)\
(btOps(pBt)->sqliteBtreeClearTable(pBt, iTable))
#define sqliteBtreeCursor(pBt, iTable, wrFlag, ppCur)\
(btOps(pBt)->sqliteBtreeCursor(pBt, iTable, wrFlag, ppCur))
#define sqliteBtreeMoveto(pCur, pKey, nKey, pRes)\
(btCOps(pCur)->sqliteBtreeMoveto(pCur, pKey, nKey, pRes))
#define sqliteBtreeDelete(pCur)\
(btCOps(pCur)->sqliteBtreeDelete(pCur))
#define sqliteBtreeInsert(pCur, pKey, nKey, pData, nData) \
(btCOps(pCur)->sqliteBtreeInsert(pCur, pKey, nKey, pData, nData))
#define sqliteBtreeFirst(pCur, pRes)\
(btCOps(pCur)->sqliteBtreeFirst(pCur, pRes))
#define sqliteBtreeLast(pCur, pRes)\
(btCOps(pCur)->sqliteBtreeLast(pCur, pRes))
#define sqliteBtreeNext(pCur, pRes)\
(btCOps(pCur)->sqliteBtreeNext(pCur, pRes))
#define sqliteBtreePrevious(pCur, pRes)\
(btCOps(pCur)->sqliteBtreePrevious(pCur, pRes))
#define sqliteBtreeKeySize(pCur, pSize)\
(btCOps(pCur)->sqliteBtreeKeySize(pCur, pSize) )
#define sqliteBtreeKey(pCur, offset, amt, zBuf)\
(btCOps(pCur)->sqliteBtreeKey(pCur, offset, amt, zBuf))
#define sqliteBtreeKeyCompare(pCur, pKey, nKey, nIgnore, pRes)\
(btCOps(pCur)->sqliteBtreeKeyCompare(pCur, pKey, nKey, nIgnore, pRes))
#define sqliteBtreeDataSize(pCur, pSize)\
(btCOps(pCur)->sqliteBtreeDataSize(pCur, pSize))
#define sqliteBtreeData(pCur, offset, amt, zBuf)\
(btCOps(pCur)->sqliteBtreeData(pCur, offset, amt, zBuf))
#define sqliteBtreeCloseCursor(pCur)\
(btCOps(pCur)->sqliteBtreeCloseCursor(pCur))
#define sqliteBtreeGetMeta(pBt, aMeta)\
(btOps(pBt)->sqliteBtreeGetMeta(pBt, aMeta))
#define sqliteBtreeUpdateMeta(pBt, aMeta)\
(btOps(pBt)->sqliteBtreeUpdateMeta(pBt, aMeta))
#define sqliteBtreeIntegrityCheck(pBt, aRoot, nRoot)\
(btOps(pBt)->sqliteBtreeIntegrityCheck(pBt, aRoot, nRoot))
#endif
#ifdef SQLITE_TEST
#if !defined(SQLITE_NO_BTREE_DEFS)
#define sqliteBtreePageDump(pBt, pgno, recursive)\
(btOps(pBt)->sqliteBtreePageDump(pBt, pgno, recursive))
#define sqliteBtreeCursorDump(pCur, aResult)\
(btCOps(pCur)->sqliteBtreeCursorDump(pCur, aResult))
#define sqliteBtreePager(pBt)\
(btOps(pBt)->sqliteBtreePager(pBt))
#endif
int btree_native_byte_order; int btree_native_byte_order;
#endif #endif