diff --git a/manifest b/manifest index 78bbaab687..6bf9b7ae46 100644 --- a/manifest +++ b/manifest @@ -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 diff --git a/manifest.uuid b/manifest.uuid index 2104dfe136..55e4356685 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f4df6664037c68e1ce539c84c852124d95cd5a56 \ No newline at end of file +85f015c9750a5eab274e82f0e2c6e8f09dc7ca70 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index eee60492ba..b4666da409 100644 --- a/src/btree.c +++ b/src/btree.c @@ -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 = inCell-1 ? pc + n : 0; @@ -534,7 +534,7 @@ static int initPage(MemPage *pPage, Pgno pgnoThis, MemPage *pParent){ if( idxu.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 && idxnCell ); assert( sz==cellSize(pPage->apCell[idx]) ); - freeSpace(pPage, idx, sz); - for(j=idx; jnCell-2; j++){ + freeSpace(pPage, Addr(pPage->apCell[idx]) - Addr(pPage), sz); + for(j=idx; jnCell-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; inCell; i++){ - int idx = addr(pPage->apCell[i]) - addr(pPage); + int idx = Addr(pPage->apCell[i]) - Addr(pPage); assert( idx>0 && idxapCell[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; inCell; i++){ - uptr x = addr(pFrom->apCell[i]); + uptr x = Addr(pFrom->apCell[i]); if( x>from && xapCell[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 ){ diff --git a/src/pager.c b/src/pager.c index a630720a56..4e759ac802 100644 --- a/src/pager.c +++ b/src/pager.c @@ -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; diff --git a/test/btree.test b/test/btree.test new file mode 100644 index 0000000000..bf849f2237 --- /dev/null +++ b/test/btree.test @@ -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 diff --git a/test/pager.test b/test/pager.test index 102c8280b3..40777e8c25 100644 --- a/test/pager.test +++ b/test/pager.test @@ -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. #