The first test file for BTree added. Simple insert and delete tests pass.

There is still a lot of work to be done, though. (CVS 228)

FossilOrigin-Name: 85f015c9750a5eab274e82f0e2c6e8f09dc7ca70
This commit is contained in:
drh 2001-06-24 20:39:41 +00:00
parent df0b3b090e
commit 7c717f750e
6 changed files with 352 additions and 30 deletions

View File

@ -1,5 +1,5 @@
C Fix\sa\sbug\sin\spager.c\sintroduced\sin\sthe\sprevious\sdelta.\s(CVS\s227)
D 2001-06-23T11:36:20
C The\sfirst\stest\sfile\sfor\sBTree\sadded.\sSimple\sinsert\sand\sdelete\stests\spass.\nThere\sis\sstill\sa\slot\sof\swork\sto\sbe\sdone,\sthough.\s(CVS\s228)
D 2001-06-24T20:39:41
F COPYRIGHT 74a8a6531a42e124df07ab5599aad63870fa0bd4
F Makefile.in 65862a30703b070209b5f5e565d75cc870962b3c
F README 51f6a4e7408b34afa5bc1c0485f61b6a4efb6958
@ -12,7 +12,7 @@ F notes/notes1.txt b7c0812b704a022e88c621146ae50955c923d464
F notes/notes2.txt 7e3fafd5e25906c1fe1e95f13b089aa398ca403e
F notes/notes3.txt 985bf688b59f1f52bfe6e4b1f896efdeffac1432
F src/TODO 38a68a489e56e9fd4a96263e0ff9404a47368ad4
F src/btree.c 0a2b66ce90f0bee87f0449235060529b96cc96e4
F src/btree.c e46ab610d0bef3d1a9f698bede21d554c42763e5
F src/btree.h 40ae2c9b6d2ba8feb03461a589ccab9afc04ec29
F src/build.c 4f6a2d551c56342cd4a0420654835be3ad179651
F src/dbbe.c b18259f99d87240cbe751021cf14dd3aa83a48af
@ -31,7 +31,7 @@ F src/ex/sizes.tcl f54bad4a2ac567624be59131a6ee42d71b41a3d7
F src/expr.c c4c24c3af1eba094a816522eb0e085bed518ee16
F src/insert.c aa528e20a787af85432a61daaea6df394bd251d7
F src/main.c 0a13c7a2beb8ce36aee43daf8c95989b200727a7
F src/pager.c d5cb53ac679d039d40661e50200a8dde6406ca15
F src/pager.c 866d4d9a736943c9a904d291bc9b66dc4a7f23de
F src/pager.h 724ac5a79b5fa704a1e1a87e421e421b3da9c1e4
F src/parse.y 8fc096948994a7ffbf61ba13129cc589f794a9cb
F src/printf.c b1e22a47be8cdf707815647239991e08e8cb69f9
@ -53,6 +53,7 @@ F src/vdbe.c f93be4414ba892df9c5589815d2a57c1fb12c820
F src/vdbe.h dc1205da434c6a9da03b5d6b089270bbc8e6d437
F src/where.c 0c542fc44bd85152dfb8507862cfe2e60c629e9f
F test/all.test 21d55a97e39e7ec5776751dc9dd8b1b51ef4a048
F test/btree.test 8db61fdd957e906d7d237bf0f578f3e8cc9fb33e
F test/copy.test b77a1214bd7756f2849d5c4fa6e715c0ff0c34eb
F test/dbbe.test a022fe2d983848f786e17ef1fc6809cfd37fb02c
F test/delete.test 50b9b1f06c843d591741dba7869433a105360dbf
@ -65,7 +66,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 475835b84cbec423a7dd3d0492b2c8701435d375
F test/pager.test aa902a867ce6b925214d28e17400001946e0e5a4
F test/printf.test 4c71871e1a75a2dacb673945fc13ddb30168798f
F test/rowid.test 128453599def7435e988216f7fe89c7450b8a9a3
F test/select1.test 223507655cdb4f9901d83fa7f5c5328e022c211f
@ -107,7 +108,7 @@ F www/opcode.tcl cb3a1abf8b7b9be9f3a228d097d6bf8b742c2b6f
F www/sqlite.tcl cb0d23d8f061a80543928755ec7775da6e4f362f
F www/tclsqlite.tcl 06f81c401f79a04f2c5ebfb97e7c176225c0aef2
F www/vdbe.tcl 0c8aaa529dd216ccbf7daaabd80985e413d5f9ad
P b31c49021c260a67b7848bc077b75a7146e31c71
R e52ea2ba0d86c859453a43591ceb35fc
P f4df6664037c68e1ce539c84c852124d95cd5a56
R 3068b07f88f8e6db3749d5669bb8ecc6
U drh
Z 86cec7512c643b5b976845158db125a4
Z ee5edd13b8c55ec829c3087fe59854aa

View File

@ -1 +1 @@
f4df6664037c68e1ce539c84c852124d95cd5a56
85f015c9750a5eab274e82f0e2c6e8f09dc7ca70

View File

@ -21,7 +21,7 @@
** http://www.hwaci.com/drh/
**
*************************************************************************
** $Id: btree.c,v 1.13 2001/06/22 19:15:00 drh Exp $
** $Id: btree.c,v 1.14 2001/06/24 20:39:41 drh Exp $
**
** This file implements a external (disk-based) database using BTrees.
** For a detailed discussion of BTrees, refer to
@ -81,7 +81,7 @@ typedef unsigned char u8;
** This macro casts a pointer to an integer. Useful for doing
** pointer arithmetic.
*/
#define addr(X) ((uptr)X)
#define Addr(X) ((uptr)X)
/*
** Forward declarations of structures used only in this file.
@ -368,8 +368,8 @@ static void defragmentPage(MemPage *pPage){
/* This routine should never be called on an overfull page. The
** following asserts verify that constraint. */
assert( addr(pCell) > addr(pPage) );
assert( addr(pCell) < addr(pPage) + SQLITE_PAGE_SIZE );
assert( Addr(pCell) > Addr(pPage) );
assert( Addr(pCell) < Addr(pPage) + SQLITE_PAGE_SIZE );
n = cellSize(pCell);
pCell->h.iNext = i<pPage->nCell-1 ? pc + n : 0;
@ -534,7 +534,7 @@ static int initPage(MemPage *pPage, Pgno pgnoThis, MemPage *pParent){
if( idx<sizeof(PageHdr) ) goto page_format_error;
pFBlk = (FreeBlk*)&pPage->u.aDisk[idx];
pPage->nFree += pFBlk->iSize;
if( pFBlk->iNext <= idx ) goto page_format_error;
if( pFBlk->iNext>0 && pFBlk->iNext <= idx ) goto page_format_error;
idx = pFBlk->iNext;
}
if( pPage->nCell==0 && pPage->nFree==0 ){
@ -666,7 +666,7 @@ static int newDatabase(Btree *pBt){
MemPage *pRoot;
PageOne *pP1;
int rc;
if( sqlitepager_pagecount(pBt->pPager)>0 ) return SQLITE_OK;
if( sqlitepager_pagecount(pBt->pPager)>1 ) return SQLITE_OK;
pP1 = pBt->page1;
rc = sqlitepager_write(pBt->page1);
if( rc ) return rc;
@ -721,7 +721,7 @@ int sqliteBtreeBeginTrans(Btree *pBt){
** remove the read lock.
*/
static void unlockBtree(Btree *pBt){
if( pBt->pCursor==0 && pBt->page1!=0 ){
if( pBt->inTrans==0 && pBt->pCursor==0 && pBt->page1!=0 ){
sqlitepager_unref(pBt->page1);
pBt->page1 = 0;
pBt->inTrans = 0;
@ -734,8 +734,9 @@ static void unlockBtree(Btree *pBt){
*/
int sqliteBtreeCommit(Btree *pBt){
int rc;
if( pBt->pCursor!=0 ) return SQLITE_ERROR;
if( pBt->pCursor!=0 || pBt->inTrans==0 ) return SQLITE_ERROR;
rc = sqlitepager_commit(pBt->pPager);
pBt->inTrans = 0;
unlockBtree(pBt);
return rc;
}
@ -747,6 +748,8 @@ int sqliteBtreeCommit(Btree *pBt){
int sqliteBtreeRollback(Btree *pBt){
int rc;
if( pBt->pCursor!=0 ) return SQLITE_ERROR;
if( pBt->inTrans==0 ) return SQLITE_OK;
pBt->inTrans = 0;
rc = sqlitepager_rollback(pBt->pPager);
unlockBtree(pBt);
return rc;
@ -1144,16 +1147,17 @@ static int moveToLeftmost(BtCursor *pCur){
** this value is as follows:
**
** *pRes<0 The cursor is left pointing at an entry that
** is larger than pKey.
** is smaller than pKey.
**
** *pRes==0 The cursor is left pointing at an entry that
** exactly matches pKey.
**
** *pRes>0 The cursor is left pointing at an entry that
** is smaller than pKey.
** is larger than pKey.
*/
int sqliteBtreeMoveto(BtCursor *pCur, void *pKey, int nKey, int *pRes){
int rc;
pCur->bSkipNext = 0;
rc = moveToRoot(pCur);
if( rc ) return rc;
for(;;){
@ -1449,8 +1453,8 @@ static void dropCell(MemPage *pPage, int idx, int sz){
int j;
assert( idx>=0 && idx<pPage->nCell );
assert( sz==cellSize(pPage->apCell[idx]) );
freeSpace(pPage, idx, sz);
for(j=idx; j<pPage->nCell-2; j++){
freeSpace(pPage, Addr(pPage->apCell[idx]) - Addr(pPage), sz);
for(j=idx; j<pPage->nCell-1; j++){
pPage->apCell[j] = pPage->apCell[j+1];
}
pPage->nCell--;
@ -1498,7 +1502,7 @@ static void relinkCellList(MemPage *pPage){
u16 *pIdx;
pIdx = &pPage->u.hdr.firstCell;
for(i=0; i<pPage->nCell; i++){
int idx = addr(pPage->apCell[i]) - addr(pPage);
int idx = Addr(pPage->apCell[i]) - Addr(pPage);
assert( idx>0 && idx<SQLITE_PAGE_SIZE );
*pIdx = idx;
pIdx = &pPage->apCell[i]->h.iNext;
@ -1521,10 +1525,10 @@ static void copyPage(MemPage *pTo, MemPage *pFrom){
pTo->nCell = pFrom->nCell;
pTo->nFree = pFrom->nFree;
pTo->isOverfull = pFrom->isOverfull;
to = addr(pTo);
from = addr(pFrom);
to = Addr(pTo);
from = Addr(pFrom);
for(i=0; i<pTo->nCell; i++){
uptr x = addr(pFrom->apCell[i]);
uptr x = Addr(pFrom->apCell[i]);
if( x>from && x<from+SQLITE_PAGE_SIZE ){
*((uptr*)&pTo->apCell[i]) = x + to - from;
}
@ -1903,13 +1907,13 @@ int sqliteBtreeInsert(
rc = clearCell(pBt, pPage->apCell[pCur->idx]);
if( rc ) return rc;
dropCell(pPage, pCur->idx, cellSize(pPage->apCell[pCur->idx]));
}else if( loc>0 ){
}else if( loc<0 && pPage->nCell>0 ){
assert( pPage->u.hdr.rightChild==0 ); /* Must be a leaf page */
pCur->idx++;
}else{
assert( pPage->u.hdr.rightChild==0 ); /* Must be a leaf page */
}
insertCell(pPage, pCur->idx, &newCell, cellSize(&newCell));
insertCell(pPage, pCur->idx, &newCell, szNew);
rc = balance(pCur->pBt, pPage, pCur);
return rc;
}
@ -2123,6 +2127,7 @@ int sqliteBtreePageDump(Btree *pBt, int pgno){
i, range, (int)pCell->h.leftChild, pCell->h.nKey, pCell->h.nData,
pCell->aPayload
);
i++;
idx = pCell->h.iNext;
}
if( idx!=0 ){

View File

@ -27,7 +27,7 @@
** all writes in order to support rollback. Locking is used to limit
** access to one or more reader or one writer.
**
** @(#) $Id: pager.c,v 1.10 2001/06/23 11:36:20 drh Exp $
** @(#) $Id: pager.c,v 1.11 2001/06/24 20:39:41 drh Exp $
*/
#include "sqliteInt.h"
#include "pager.h"
@ -476,6 +476,7 @@ int sqlitepager_open(
pPager->errMask = 0;
pPager->pFirst = 0;
pPager->pLast = 0;
pPager->nExtra = nExtra;
memset(pPager->aHash, 0, sizeof(pPager->aHash));
*ppPager = pPager;
return SQLITE_OK;

315
test/btree.test Normal file
View File

@ -0,0 +1,315 @@
# Copyright (c) 1999, 2000 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 file implements regression tests for SQLite library. The
# focus of this script is btree database backend
#
# $Id: btree.test,v 1.1 2001/06/24 20:39:41 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
if {$dbprefix!="memory:" && [info commands btree_open]!=""} {
# Basic functionality. Open and close a database.
#
do_test btree-1.1 {
file delete -force test1.bt
file delete -force test1.bt-journal
set rc [catch {btree_open test1.bt} ::b1]
} {0}
do_test btree-1.2 {
set rc [catch {btree_open test1.bt} ::b2]
} {0}
do_test btree-1.3 {
set rc [catch {btree_close $::b2} msg]
lappend rc $msg
} {0 {}}
# Do an insert and verify that the database file grows in size.
#
do_test btree-1.4 {
set rc [catch {btree_begin_transaction $::b1} msg]
lappend rc $msg
} {0 {}}
do_test btree-1.5 {
set rc [catch {btree_cursor $::b1 2} ::c1]
if {$rc} {lappend rc $::c1}
set rc
} {0}
do_test btree-1.6 {
set rc [catch {btree_insert $::c1 one 1.00} msg]
lappend rc $msg
} {0 {}}
do_test btree-1.7 {
btree_key $::c1
} {one}
do_test btree-1.8 {
btree_data $::c1
} {1.00}
do_test btree-1.9 {
set rc [catch {btree_close_cursor $::c1} msg]
lappend rc $msg
} {0 {}}
do_test btree-1.10 {
set rc [catch {btree_commit $::b1} msg]
lappend rc $msg
} {0 {}}
do_test btree-1.11 {
file size test1.bt
} {2048}
# Reopen the database and attempt to read the record that we wrote.
#
do_test btree-2.1 {
set rc [catch {btree_cursor $::b1 2} ::c1]
if {$rc} {lappend rc $::c1}
set rc
} {0}
do_test btree-2.2 {
btree_move_to $::c1 abc
} {1}
do_test btree-2.3 {
btree_move_to $::c1 xyz
} {-1}
do_test btree-2.4 {
btree_move_to $::c1 one
} {0}
do_test btree-2.5 {
btree_key $::c1
} {one}
do_test btree-2.6 {
btree_data $::c1
} {1.00}
# Do some additional inserts
#
do_test btree-3.1 {
btree_begin_transaction $::b1
btree_insert $::c1 two 2.00
btree_key $::c1
} {two}
do_test btree-3.2 {
btree_insert $::c1 three 3.00
btree_key $::c1
} {three}
do_test btree-3.4 {
btree_insert $::c1 four 4.00
btree_key $::c1
} {four}
do_test btree-3.5 {
btree_insert $::c1 five 5.00
btree_key $::c1
} {five}
do_test btree-3.6 {
btree_insert $::c1 six 6.00
btree_key $::c1
} {six}
#btree_page_dump $::b1 2
do_test btree-3.7 {
set rc [btree_move_to $::c1 {}]
expr {$rc>0}
} {1}
do_test btree-3.8 {
btree_key $::c1
} {five}
do_test btree-3.9 {
btree_data $::c1
} {5.00}
do_test btree-3.10 {
btree_next $::c1
btree_key $::c1
} {four}
do_test btree-3.11 {
btree_data $::c1
} {4.00}
do_test btree-3.12 {
btree_next $::c1
btree_key $::c1
} {one}
do_test btree-3.13 {
btree_data $::c1
} {1.00}
do_test btree-3.14 {
btree_next $::c1
btree_key $::c1
} {six}
do_test btree-3.15 {
btree_data $::c1
} {6.00}
do_test btree-3.16 {
btree_next $::c1
btree_key $::c1
} {three}
do_test btree-3.17 {
btree_data $::c1
} {3.00}
do_test btree-3.18 {
btree_next $::c1
btree_key $::c1
} {two}
do_test btree-3.19 {
btree_data $::c1
} {2.00}
do_test btree-3.20 {
btree_next $::c1
btree_key $::c1
} {}
do_test btree-3.21 {
btree_data $::c1
} {}
# Commit the changes, reopen and reread the data
#
do_test btree-3.22 {
set rc [catch {btree_close_cursor $::c1} msg]
lappend rc $msg
} {0 {}}
do_test btree-3.23 {
set rc [catch {btree_commit $::b1} msg]
lappend rc $msg
} {0 {}}
do_test btree-3.24 {
file size test1.bt
} {2048}
do_test btree-3.25 {
set rc [catch {btree_cursor $::b1 2} ::c1]
if {$rc} {lappend rc $::c1}
set rc
} {0}
do_test btree-3.26 {
set rc [btree_move_to $::c1 {}]
expr {$rc>0}
} {1}
do_test btree-3.27 {
btree_key $::c1
} {five}
do_test btree-3.28 {
btree_data $::c1
} {5.00}
do_test btree-3.29 {
btree_next $::c1
btree_key $::c1
} {four}
do_test btree-3.30 {
btree_data $::c1
} {4.00}
do_test btree-3.31 {
btree_next $::c1
btree_key $::c1
} {one}
do_test btree-3.32 {
btree_data $::c1
} {1.00}
do_test btree-3.33 {
btree_next $::c1
btree_key $::c1
} {six}
do_test btree-3.34 {
btree_data $::c1
} {6.00}
do_test btree-3.35 {
btree_next $::c1
btree_key $::c1
} {three}
do_test btree-3.36 {
btree_data $::c1
} {3.00}
do_test btree-3.37 {
btree_next $::c1
btree_key $::c1
} {two}
do_test btree-3.38 {
btree_data $::c1
} {2.00}
do_test btree-3.39 {
btree_next $::c1
btree_key $::c1
} {}
do_test btree-3.40 {
btree_data $::c1
} {}
# Now try a delete
#
do_test btree-4.1 {
btree_begin_transaction $::b1
btree_move_to $::c1 one
btree_key $::c1
} {one}
do_test btree-4.2 {
btree_delete $::c1
} {}
do_test btree-4.3 {
btree_key $::c1
} {six}
do_test btree-4.4 {
btree_next $::c1
btree_key $::c1
} {six}
do_test btree-4.5 {
btree_next $::c1
btree_key $::c1
} {three}
do_test btree-4.4 {
btree_move_to $::c1 {}
set r {}
while 1 {
set key [btree_key $::c1]
if {$key==""} break
lappend r $key
lappend r [btree_data $::c1]
btree_next $::c1
}
set r
} {five 5.00 four 4.00 six 6.00 three 3.00 two 2.00}
# Commit and make sure the delete is still there.
#
do_test btree-4.5 {
btree_close_cursor $::c1
btree_commit $::b1
set ::c1 [btree_cursor $::b1 2]
btree_move_to $::c1 {}
set r {}
while 1 {
set key [btree_key $::c1]
if {$key==""} break
lappend r $key
lappend r [btree_data $::c1]
btree_next $::c1
}
set r
} {five 5.00 four 4.00 six 6.00 three 3.00 two 2.00}
do_test btree-99.1 {
btree_close $::b1
} {}
} ;# end if( not mem: and has pager_open command );
finish_test

View File

@ -23,13 +23,13 @@
# This file implements regression tests for SQLite library. The
# focus of this script is page cache subsystem.
#
# $Id: pager.test,v 1.5 2001/05/24 21:06:36 drh Exp $
# $Id: pager.test,v 1.6 2001/06/24 20:39:41 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
if {$dbprefix!="mem:" && [info commands pager_open]!=""} {
if {$dbprefix!="memory:" && [info commands pager_open]!=""} {
# Basic sanity check. Open and close a pager.
#