mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-07 02:42:48 +03:00
Begin adding BTree code (CVS 213)
FossilOrigin-Name: bdb1c425f577d455155982ee2cd8cb686bcaf0da
This commit is contained in:
14
manifest
14
manifest
@@ -1,5 +1,5 @@
|
||||
C Version\s1.0.31\s(CVS\s472)
|
||||
D 2001-04-15T02:30:00
|
||||
C Begin\sadding\sBTree\scode\s(CVS\s213)
|
||||
D 2001-04-17T20:09:11
|
||||
F COPYRIGHT 74a8a6531a42e124df07ab5599aad63870fa0bd4
|
||||
F Makefile.in ac01d6145714b0d1c9e99382caf03cf30d6f4c8d
|
||||
F README 51f6a4e7408b34afa5bc1c0485f61b6a4efb6958
|
||||
@@ -9,6 +9,8 @@ F configure.in 6940e3f88bf3d28a10c73b06ab99fd3a7e039a61
|
||||
F doc/lemon.html e233a3e97a779c7a87e1bc4528c664a58e49dd47
|
||||
F doc/report1.txt 734cbae63b1310cc643fe5e9e3da1ab55a79b99e
|
||||
F src/TODO 38a68a489e56e9fd4a96263e0ff9404a47368ad4
|
||||
F src/btree.c 670b20349bd1d1448cc90f7b9487c2bf7a5c039c
|
||||
F src/btree.h f21c240d0c95f93e2a128106d04a6c448ed0eb94
|
||||
F src/build.c 4f6a2d551c56342cd4a0420654835be3ad179651
|
||||
F src/dbbe.c ec82c602c598748204a61a35ab0c31e34ca58223
|
||||
F src/dbbe.h 7235b15c6c5d8be0c4da469cef9620cee70b1cc8
|
||||
@@ -59,7 +61,7 @@ F test/insert2.test 732405e30331635af8d159fccabe835eea5cd0c6
|
||||
F test/lock.test bca7d53de73138b1f670a2fbdb1f481ff7eaa45a
|
||||
F test/main.test da635f9e078cd21ddf074e727381a715064489ff
|
||||
F test/malloc.test 3daa97f6a9577d8f4c6e468b274333af19ce5861
|
||||
F test/pager.test 4c27be3e0da89caa36fa3c2b84468785f330acca
|
||||
F test/pager.test 3416a155c2dc3b1b3c07d4bb0192cbb15b76a90c
|
||||
F test/printf.test 4c71871e1a75a2dacb673945fc13ddb30168798f
|
||||
F test/rowid.test 128453599def7435e988216f7fe89c7450b8a9a3
|
||||
F test/select1.test 223507655cdb4f9901d83fa7f5c5328e022c211f
|
||||
@@ -101,7 +103,7 @@ F www/opcode.tcl cb3a1abf8b7b9be9f3a228d097d6bf8b742c2b6f
|
||||
F www/sqlite.tcl cb0d23d8f061a80543928755ec7775da6e4f362f
|
||||
F www/tclsqlite.tcl 06f81c401f79a04f2c5ebfb97e7c176225c0aef2
|
||||
F www/vdbe.tcl 0c8aaa529dd216ccbf7daaabd80985e413d5f9ad
|
||||
P 1f07abe46e2de8c5d9659bd5a78efe4ce23144ae
|
||||
R 6b66dff388a84887995d516ce20e212a
|
||||
P a7bfcbb4131ab17a58d5e843c418b2e1a3ab2abc
|
||||
R a9d053b754fd8fb60eea783a8c6d6da7
|
||||
U drh
|
||||
Z 1ee28b0946e3569d6ec390d67bea5d2f
|
||||
Z b0f122553586c19814acf39c12755271
|
||||
|
@@ -1 +1 @@
|
||||
a7bfcbb4131ab17a58d5e843c418b2e1a3ab2abc
|
||||
bdb1c425f577d455155982ee2cd8cb686bcaf0da
|
266
src/btree.c
Normal file
266
src/btree.c
Normal file
@@ -0,0 +1,266 @@
|
||||
/*
|
||||
** Copyright (c) 2001 D. Richard Hipp
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or
|
||||
** modify it under the terms of the GNU General Public
|
||||
** License as published by the Free Software Foundation; either
|
||||
** version 2 of the License, or (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
** General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public
|
||||
** License along with this library; if not, write to the
|
||||
** Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
** Boston, MA 02111-1307, USA.
|
||||
**
|
||||
** Author contact information:
|
||||
** drh@hwaci.com
|
||||
** http://www.hwaci.com/drh/
|
||||
**
|
||||
*************************************************************************
|
||||
** $Id: btree.c,v 1.1 2001/04/17 20:09:11 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "pager.h"
|
||||
#include "btree.h"
|
||||
#include <assert.h>
|
||||
|
||||
typedef unsigned int u32;
|
||||
|
||||
/*
|
||||
** Everything we need to know about an open database
|
||||
*/
|
||||
struct Btree {
|
||||
Pager *pPager; /* The page cache */
|
||||
BtCursor *pCursor; /* All open cursors */
|
||||
u32 *page1; /* First page of the database */
|
||||
int inTrans; /* True if a transaction is current */
|
||||
};
|
||||
typedef Btree Bt;
|
||||
|
||||
/*
|
||||
** The maximum depth of a cursor
|
||||
*/
|
||||
#define MX_LEVEL 20
|
||||
|
||||
/*
|
||||
** Within a cursor, each level off the search tree is an instance of
|
||||
** this structure.
|
||||
*/
|
||||
typedef struct BtIdxpt BtIdxpt;
|
||||
struct BtIdxpt {
|
||||
Pgno pgno; /* The page number */
|
||||
u32 *aPage; /* The page data */
|
||||
int idx; /* Index into pPage[] */
|
||||
};
|
||||
|
||||
/*
|
||||
** Everything we need to know about a cursor
|
||||
*/
|
||||
struct BtCursor {
|
||||
Btree *pBt; /* The whole database */
|
||||
BtCursor *pPrev, *pNext; /* Linked list of all cursors */
|
||||
int valid; /* True if the cursor points to something */
|
||||
int nLevel; /* Number of levels of indexing used */
|
||||
BtIdxpt aLevel[MX_LEVEL]; /* The index levels */
|
||||
};
|
||||
|
||||
/*
|
||||
** The first page contains the following additional information:
|
||||
**
|
||||
** MAGIC-1
|
||||
** MAGIC-2
|
||||
** First free block
|
||||
*/
|
||||
#define EXTRA_PAGE_1_CELLS 3
|
||||
#define MAGIC_1 0x7264dc61
|
||||
#define MAGIC_2 0x54e55d9e
|
||||
|
||||
/*
|
||||
** Open a new database
|
||||
*/
|
||||
int sqliteBtreeOpen(const char *zFilename, int mode, Btree **ppBtree){
|
||||
Btree *pBt;
|
||||
|
||||
pBt = sqliteMalloc( sizeof(*pBt) );
|
||||
if( pBt==0 ){
|
||||
**ppBtree = 0;
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
rc = sqlitepager_open(&pBt->pPager, zFilename, 100);
|
||||
if( rc!=SQLITE_OK ){
|
||||
if( pBt->pPager ) sqlitepager_close(pBt->pPager);
|
||||
sqliteFree(pBt);
|
||||
*ppBtree = 0;
|
||||
return rc;
|
||||
}
|
||||
pBt->pCursor = 0;
|
||||
pBt->page1 = 0;
|
||||
*ppBtree = pBt;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Close an open database and invalidate all cursors.
|
||||
*/
|
||||
int sqliteBtreeClose(Btree *pBt){
|
||||
while( pBt->pCursor ){
|
||||
sqliteBtreeCloseCursor(pBt->pCursor);
|
||||
}
|
||||
sqlitepager_close(pBt->pPager);
|
||||
sqliteFree(pBt);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Start a new transaction
|
||||
*/
|
||||
int sqliteBtreeBeginTrans(Btree *pBt){
|
||||
int rc;
|
||||
if( pBt->inTrans ) return SQLITE_ERROR;
|
||||
if( pBt->page1==0 ){
|
||||
rc = sqlitepager_get(pBt->pPager, 1, &pBt->page1);
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
}
|
||||
rc = sqlitepager_write(pBt->page1);
|
||||
if( rc==SQLITE_OK ){
|
||||
pBt->inTrans = 1;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Get a reference to page1 of the database file. This will
|
||||
** also acquire a readlock on that file.
|
||||
*/
|
||||
static int lockBtree(Btree *pBt){
|
||||
int rc;
|
||||
if( pBt->page1 ) return SQLITE_OK;
|
||||
rc = sqlitepager_get(pBt->pPager, 1, &pBt->page1);
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
/* Sanity checking on the database file format */
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Remove the last reference to the database file. This will
|
||||
** remove the read lock.
|
||||
*/
|
||||
static void unlockBtree(Btree *pBt){
|
||||
if( pBt->pCursor==0 && pBt->page1!=0 ){
|
||||
sqlitepager_unref(pBt->page1);
|
||||
pBt->page1 = 0;
|
||||
pBt->inTrans = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Commit the transaction currently in progress. All cursors
|
||||
** must be closed before this routine is called.
|
||||
*/
|
||||
int sqliteBtreeCommit(Btree *pBt){
|
||||
int rc;
|
||||
assert( pBt->pCursor==0 );
|
||||
rc = sqlitepager_commit(pBt->pPager);
|
||||
unlockBtree(pBt);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Rollback the transaction in progress. All cursors must be
|
||||
** closed before this routine is called.
|
||||
*/
|
||||
int sqliteBtreeRollback(Btree *pBt){
|
||||
int rc;
|
||||
assert( pBt->pCursor==0 );
|
||||
rc = sqlitepager_rollback(pBt->pPager);
|
||||
unlockBtree(pBt);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Create a new cursor. The act of acquiring a cursor
|
||||
** gets a read lock on the database file.
|
||||
*/
|
||||
int sqliteBtreeCursor(Btree *pBt, BtCursor **ppCur){
|
||||
int rc;
|
||||
BtCursor *pCur;
|
||||
if( pBt->page1==0 ){
|
||||
rc = lockBtree(pBt);
|
||||
if( rc!=SQLITE_OK ){
|
||||
*ppCur = 0;
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
pCur = sqliteMalloc( sizeof(*pCur) );
|
||||
if( pCur==0 ){
|
||||
*ppCur = 0;
|
||||
unlockBtree(pBt);
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
pCur->pPrev = 0;
|
||||
pCur->pNext = pBt->pCursor;
|
||||
if( pCur->pNext ){
|
||||
pCur->pNext->pPrev = pCur;
|
||||
}
|
||||
pBt->pCursor = pCur;
|
||||
pCur->pBt = pBt;
|
||||
pCur->nLevel = 1;
|
||||
pCur->aLevel[0].pgno = 1;
|
||||
pCur->aLevel[0].aPage = pBt->page1;
|
||||
pCur->aLevel[0].idx = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Close a cursor.
|
||||
*/
|
||||
int sqliteBtreeCloseCursor(BtCursor *pCur){
|
||||
Btree *pBt = pCur->pBt;
|
||||
int i;
|
||||
if( pCur->pPrev ){
|
||||
pCur->pPrev->pNext = pCur->pNext;
|
||||
}else{
|
||||
pBt->pCursor = pCur->pNext;
|
||||
}
|
||||
if( pCur->pNext ){
|
||||
pCur->pNext->pPrev = pCur->pPrev;
|
||||
}
|
||||
for(i=pCur->nLevel-1; i>0; i--){
|
||||
sqlitepager_unref(pCur->aLevel[i].aPage);
|
||||
}
|
||||
if( pBt->pCursor==0 && pBt->inTrans==0 ){
|
||||
unlockBtree(pBt);
|
||||
}
|
||||
sqliteFree(pCur);
|
||||
}
|
||||
|
||||
int sqliteBtreeKeySize(BtCursor *pCur){
|
||||
int nEntry;
|
||||
u32 *aPage;
|
||||
BtIdxpt *pIdx;
|
||||
int offset;
|
||||
if( !pCur->valid ) return 0;
|
||||
pIdx = &pCur->aLevel[pCur->nLevel-1];
|
||||
aPage = pIdx->aPage;
|
||||
offset = (pIdx->pgno==1)*EXTRA_PAGE_1_CELLS;
|
||||
nEntry = aPage[offset];
|
||||
if( pIdx->idx<nEntry ){
|
||||
|
||||
}
|
||||
int sqliteBtreeKey(BtCursor*, int offset, int amt, char *zBuf);
|
||||
int sqliteBtreeDataSize(BtCursor*);
|
||||
int sqliteBtreeData(BtCursor*, int offset, int amt, char *zBuf);
|
||||
|
||||
|
||||
/* Move the cursor so that it points to an entry near pKey.
|
||||
** Return 0 if the cursor is left pointing exactly at pKey.
|
||||
** Return -1 if the cursor points to the largest entry less than pKey.
|
||||
** Return 1 if the cursor points to the smallest entry greater than pKey.
|
||||
*/
|
||||
int sqliteBtreeMoveto(BtCursor*, void *pKey, int nKey);
|
||||
int sqliteBtreeDelete(BtCursor*);
|
||||
int sqliteBtreeInsert(BtCursor*, void *pKey, int nKey, void *pData, int nData);
|
||||
int sqliteBtreeNext(BtCursor*);
|
56
src/btree.h
Normal file
56
src/btree.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
** Copyright (c) 2001 D. Richard Hipp
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or
|
||||
** modify it under the terms of the GNU General Public
|
||||
** License as published by the Free Software Foundation; either
|
||||
** version 2 of the License, or (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
** General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public
|
||||
** License along with this library; if not, write to the
|
||||
** Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
** Boston, MA 02111-1307, USA.
|
||||
**
|
||||
** Author contact information:
|
||||
** drh@hwaci.com
|
||||
** http://www.hwaci.com/drh/
|
||||
**
|
||||
*************************************************************************
|
||||
** This header file defines the interface that the sqlite B-Tree file
|
||||
** subsystem.
|
||||
**
|
||||
** @(#) $Id: btree.h,v 1.1 2001/04/17 20:09:11 drh Exp $
|
||||
*/
|
||||
|
||||
typedef struct Btree Btree;
|
||||
typedef struct BtCursor BtCursor;
|
||||
|
||||
int sqliteBtreeOpen(const char *zFilename, int mode, Btree **ppBtree);
|
||||
int sqliteBtreeClose(Btree*);
|
||||
|
||||
int sqliteBtreeBeginTrans(Btree*);
|
||||
int sqliteBtreeCommit(Btree*);
|
||||
int sqliteBtreeRollback(Btree*);
|
||||
|
||||
|
||||
int sqliteBtreeCursor(Btree*, BtCursor **ppCur);
|
||||
|
||||
/* Move the cursor so that it points to an entry near pKey.
|
||||
** Return 0 if the cursor is left pointing exactly at pKey.
|
||||
** Return -1 if the cursor points to the largest entry less than pKey.
|
||||
** Return 1 if the cursor points to the smallest entry greater than pKey.
|
||||
*/
|
||||
int sqliteBtreeMoveto(BtCursor*, void *pKey, int nKey);
|
||||
int sqliteBtreeDelete(BtCursor*);
|
||||
int sqliteBtreeInsert(BtCursor*, void *pKey, int nKey, void *pData, int nData);
|
||||
int sqliteBtreeNext(BtCursor*);
|
||||
int sqliteBtreeKeySize(BtCursor*);
|
||||
int sqliteBtreeKey(BtCursor*, int offset, int amt, char *zBuf);
|
||||
int sqliteBtreeDataSize(BtCursor*);
|
||||
int sqliteBtreeData(BtCursor*, int offset, int amt, char *zBuf);
|
||||
int sqliteBtreeCloseCursor(BtCursor*);
|
@@ -23,7 +23,7 @@
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this script is page cache subsystem.
|
||||
#
|
||||
# $Id: pager.test,v 1.2 2001/04/15 02:27:25 drh Exp $
|
||||
# $Id: pager.test,v 1.3 2001/04/17 20:09:11 drh Exp $
|
||||
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
@@ -171,7 +171,7 @@ do_test pager-2.99 {
|
||||
|
||||
do_test pager-3.1 {
|
||||
set v [catch {
|
||||
set ::p1 [pager_open ptf1.db 5]
|
||||
set ::p1 [pager_open ptf1.db 15]
|
||||
} msg]
|
||||
if {$v} {lappend v $msg}
|
||||
set v
|
||||
@@ -205,6 +205,29 @@ for {set i 2} {$i<=20} {incr i} {
|
||||
set v
|
||||
}] "Page-$i"
|
||||
}
|
||||
for {set i 1} {$i<=20} {incr i} {
|
||||
regsub -all CNT {
|
||||
set ::g1 [page_get $::p1 CNT]
|
||||
set ::g2 [page_get $::p1 CNT]
|
||||
set ::vx [page_read $::g2]
|
||||
expr {$::g1==$::g2}
|
||||
} $i body;
|
||||
do_test pager-3.7.$i.1 $body {1}
|
||||
regsub -all CNT {
|
||||
page_unref $::g2
|
||||
set vy [page_read $::g1]
|
||||
expr {$vy==$::vx}
|
||||
} $i body;
|
||||
do_test pager-3.7.$i.2 $body {1}
|
||||
regsub -all CNT {
|
||||
page_unref $::g1
|
||||
set gx [page_get $::p1 CNT]
|
||||
set vy [page_read $gx]
|
||||
page_unref $gx
|
||||
expr {$vy==$::vx}
|
||||
} $i body;
|
||||
do_test pager-3.7.$i.3 $body {1}
|
||||
}
|
||||
do_test pager-3.99 {
|
||||
pager_close $::p1
|
||||
} {}
|
||||
|
Reference in New Issue
Block a user