-C Add\sflags\svalues\sto\sthe\sMem\sstructure\sto\saccomodate\sBLOBs\sand\sto\sshow\nthe\srepresentation\sof\sstrings.\s(CVS\s1341)
-D 2004-05-10T12:07:11
+C The\sbtree.c\smodule\snow\spasses\sall\sthe\shistorical\sregression\stests.\s\sNew\stests\nfor\snew\sfunctionality\sstill\sneed\sto\sbe\sadded.\s(CVS\s1342)
+D 2004-05-10T16:18:48
F Makefile.in ab7b0d5118e2da97bac66be8684a1034e3500f5a
F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
F sqlite.pc.in 30552343140c53304c2a658c080fbe810cd09ca2
F src/attach.c fa9a58234406d84eeb900517d0c0adc4b2da051a
F src/auth.c 5c2f0bea4729c98c2be3b69d6b466fc51448fe79
-F src/btree.c b5950a1fece49f4a57f49a88b80610aae120bf16
+F src/btree.c 1b29a6915b2ac5d5c9919e1a461a09bc1e7b8a76
F src/btree.h 7c3939a2e5f782c1ebac3bf43c02a16febad6df1
F src/btree_rb.c 9d7973e266ee6f9c61ce592f68742ce9cd5b10e5
F src/build.c 8d9965b3ce5dcc1bd4dac60bd0f14524fea269cb
F src/random.c eff68e3f257e05e81eae6c4d50a51eb88beb4ff3
F src/select.c 9290439282fdc787fdf34d8600dec3a360275c92
F src/shell.c 255b8b9023cb5274f56d87df437e8ce6ef810b91
-F src/sqlite.h.in cfdb920ed7b68692720263f8b662f276fe15f33c
+F src/sqlite.h.in 799c5e726296ec7bc20e6407cdf4df0e0bc00c0c
F src/sqliteInt.h 3151a1c14fc07f96169e904913d28c7ab173d8ca
F src/table.c af14284fa36c8d41f6829e3f2819dce07d3e2de2
F src/tclsqlite.c a38bf2263a097fcc9603e818c291151de1782c11
F src/test1.c 79956f70dddd1a28f8577bbd61c8cf28e5875eb8
F src/test2.c 6195a1ca2c8d0d2d93644e86da3289b403486872
-F src/test3.c d6d9d943de0926688fed4c4f5f5b345afda1ba73
+F src/test3.c bcc9a49e8d2cb7864efb964974e1807f3e0c30c4
F src/test4.c b3fab9aea7a8940a8a7386ce1c7e2157b09bd296
F src/test5.c eb39aac8fed61bd930b92613cd705c145244074a
F src/tokenize.c e7536dd31205d5afb76c1bdc832dea009c7a3847
F test/bigrow.test 8ab252dba108f12ad64e337b0f2ff31a807ac578
F test/bind.test 56a57043b42c4664ca705f6050e56717a8a6699a
F test/btree.test ed5781db83b6c1de02e62781d44915a9abe3450a
-F test/btree2.test aed860c48f873f1678a94786bc1e6eab09a0419b
+F test/btree2.test aa4a6d05b1ea90b1acaf83ba89039dd302a88635
F test/btree4.test 3797b4305694c7af6828675b0f4b1424b8ca30e4
F test/capi2.test ec96e0e235d87b53cbaef3d8e3e0f8ccf32c71ca
F test/conflict.test 0911bb2f079046914a6e9c3341b36658c4e2103e
F www/tclsqlite.tcl b9271d44dcf147a93c98f8ecf28c927307abd6da
F www/vdbe.tcl 9b9095d4495f37697fd1935d10e14c6015e80aa1
F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4
-P ac46bd686d2211813d254af578fe4e211162bc4b
-R 4a9fc99f56e83c67635aeaf2f3df4688
+P 3af283f483f75795d5b03dc8fd886aaf326d50b7
+R 6546c34bdaf9d2a72d3829b11104409d
U drh
-Z 2e2c13a294ecee6121fff95c45eff825
+Z 3dbc1d278bc85c72de8f6c60be466152
** May you share freely, never taking more than you give.
**
*************************************************************************
-** $Id: btree.c,v 1.121 2004/05/10 10:34:34 danielk1977 Exp $
+** $Id: btree.c,v 1.122 2004/05/10 16:18:48 drh Exp $
**
** This file implements a external (disk-based) database using BTrees.
** For a detailed discussion of BTrees, refer to
static int allocateSpace(MemPage *pPage, int nByte){
int addr, pc, hdr;
int size;
+ int nFrag;
unsigned char *data;
#ifndef NDEBUG
int cnt = 0;
if( nByte<4 ) nByte = 4;
if( pPage->nFree<nByte || pPage->isOverfull ) return 0;
hdr = pPage->hdrOffset;
- if( data[hdr+5]>=60 ){
+ nFrag = data[hdr+5];
+ if( nFrag>=60 || nFrag>pPage->nFree-nByte ){
defragmentPage(pPage);
}
addr = hdr+1;
*/
int sqlite3BtreeRollback(Btree *pBt){
int rc;
+ MemPage *pPage1;
if( pBt->inTrans==0 ) return SQLITE_OK;
pBt->inTrans = 0;
pBt->inStmt = 0;
- rc = pBt->readOnly ? SQLITE_OK : sqlite3pager_rollback(pBt->pPager);
+ if( pBt->readOnly ){
+ rc = SQLITE_OK;
+ }else{
+ 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
+ ** set correctly. */
+ if( getPage(pBt, 1, &pPage1)==SQLITE_OK ){
+ releasePage(pPage1);
+ }
+ }
invalidateCursors(pBt);
unlockBtreeIfUnused(pBt);
return rc;
goto create_cursor_exception;
}
pCur->pgnoRoot = (Pgno)iTable;
+ if( iTable==1 && sqlite3pager_pagecount(pBt->pPager)==0 ){
+ rc = SQLITE_EMPTY;
+ goto create_cursor_exception;
+ }
rc = getAndInitPage(pBt, pCur->pgnoRoot, &pCur->pPage, 0);
if( rc!=SQLITE_OK ){
goto create_cursor_exception;
** content of the cell.
**
** If the cell content will fit on the page, then put it there. If it
-** will not fit, then just make pPage->aCell[i] point to the content
-** and set pPage->isOverfull.
+** will not fit and pTemp is not NULL, then make a copy of the content
+** into pTemp, set pPage->aCell[i] point to pTemp, and set pPage->isOverfull.
+** If the content will not fit and pTemp is NULL, then make pPage->aCell[i]
+** point to pCell and set pPage->isOverfull.
**
** Try to maintain the integrity of the linked list of cells. But if
** the cell being inserted does not fit on the page, this will not be
** pPage->aCell[] and set the pPage->needRelink flag so that we will
** know to rebuild the linked list later.
*/
-static void insertCell(MemPage *pPage, int i, unsigned char *pCell, int sz){
+static void insertCell(
+ MemPage *pPage, /* Page into which we are copying */
+ int i, /* Which cell on pPage to insert after */
+ u8 *pCell, /* Text of the new cell to insert */
+ int sz, /* Bytes of data in pCell */
+ u8 *pTemp /* Temp storage space for pCell, if needed */
+){
int idx, j;
assert( i>=0 && i<=pPage->nCell );
assert( sz==cellSize(pPage, pCell) );
pPage->nCell++;
if( idx<=0 ){
pPage->isOverfull = 1;
- pPage->aCell[i] = pCell;
+ if( pTemp ){
+ memcpy(pTemp, pCell, sz);
+ }else{
+ pTemp = pCell;
+ }
+ pPage->aCell[i] = pTemp;
}else{
u8 *data = pPage->aData;
memcpy(&data[idx], pCell, sz);
int idxDiv[NB]; /* Indices of divider cells in pParent */
u8 *apDiv[NB]; /* Divider cells in pParent */
u8 aTemp[NB][MX_CELL_SIZE]; /* Temporary holding area for apDiv[] */
+ u8 aInsBuf[NB][MX_CELL_SIZE];/* Space to hold dividers cells during insert */
int cntNew[NB+1]; /* Index in aCell[] of cell after i-th page */
int szNew[NB+1]; /* Combined size of cells place on i-th page */
u8 *apCell[(MX_CELL+2)*NB]; /* All cells from pages being balanced */
resizeCellArray(pPage, pChild->nCell);
for(i=0; i<pChild->nCell; i++){
insertCell(pPage, i, pChild->aCell[i],
- cellSize(pChild, pChild->aCell[i]));
+ cellSize(pChild, pChild->aCell[i]), 0);
}
freePage(pChild);
TRACE(("BALANCE: child %d transfer to page 1\n", pChild->pgno));
apNew[minI] = pT;
}
}
+ TRACE(("BALANCE: old: %d %d %d new: %d %d %d %d\n",
+ pgnoOld[0],
+ nOld>=2 ? pgnoOld[1] : 0,
+ nOld>=3 ? pgnoOld[2] : 0,
+ pgnoNew[0],
+ nNew>=2 ? pgnoNew[1] : 0,
+ nNew>=3 ? pgnoNew[2] : 0,
+ nNew>=4 ? pgnoNew[3] : 0));
+
/*
** Evenly distribute the data in apCell[] across the new pages.
resizeCellArray(pNew, cntNew[i] - j);
while( j<cntNew[i] ){
assert( pNew->nFree>=szCell[j] );
- insertCell(pNew, pNew->nCell, apCell[j], szCell[j]);
+ insertCell(pNew, pNew->nCell, apCell[j], szCell[j], 0);
j++;
}
assert( pNew->nCell>0 );
relinkCellList(pNew);
if( i<nNew-1 && j<nCell ){
u8 *pCell = apCell[j];
+ u8 *pTemp;
if( !pNew->leaf ){
- memcpy(&pNew->aData[6], &apCell[j][2], 4);
+ memcpy(&pNew->aData[6], pCell+2, 4);
+ pTemp = 0;
}else{
pCell -= 4;
+ pTemp = aInsBuf[i];
}
- insertCell(pParent, nxDiv, pCell, szCell[j]+leafCorrection);
+ insertCell(pParent, nxDiv, pCell, szCell[j]+leafCorrection, pTemp);
put4byte(&pParent->aCell[nxDiv][2], pNew->pgno);
j++;
nxDiv++;
}else{
assert( pPage->leaf );
}
- insertCell(pPage, pCur->idx, newCell, szNew);
+ insertCell(pPage, pCur->idx, newCell, szNew, 0);
rc = balance(pPage);
/* sqlite3BtreePageDump(pCur->pBt, pCur->pgnoRoot, 1); */
/* fflush(stdout); */
unsigned char *pNext;
int szNext;
int notUsed;
- unsigned char tempbuf[4];
+ unsigned char tempCell[MX_CELL_SIZE];
getTempCursor(pCur, &leafCur);
rc = sqlite3BtreeNext(&leafCur, ¬Used);
if( rc!=SQLITE_OK ){
dropCell(pPage, pCur->idx, cellSize(pPage, pCell));
pNext = leafCur.pPage->aCell[leafCur.idx];
szNext = cellSize(leafCur.pPage, pNext);
- memcpy(tempbuf, &pNext[-2], 4);
- put4byte(&pNext[-2], pgnoChild);
- insertCell(pPage, pCur->idx, &pNext[-4], szNext+4);
+ assert( sizeof(tempCell)>=szNext+4 );
+ insertCell(pPage, pCur->idx, pNext-4, szNext+4, tempCell);
+ put4byte(pPage->aCell[pCur->idx]+2, pgnoChild);
rc = balance(pPage);
if( rc ) return rc;
- memcpy(&pNext[-2], tempbuf, 4);
dropCell(leafCur.pPage, leafCur.idx, szNext);
rc = balance(leafCur.pPage);
releaseTempCursor(&leafCur);
# This file implements regression tests for SQLite library. The
# focus of this script is btree database backend
#
-# $Id: btree2.test,v 1.12 2004/05/09 20:40:11 drh Exp $
+# $Id: btree2.test,v 1.13 2004/05/10 16:18:48 drh Exp $
set testdir [file dirname $argv0]
# for foreground and background tables.
#
# 2. The union of the foreground an background tables consists of N entries
-# where each entry an L-digit key. (Actually, some keys can be longer
+# where each entry has an L-digit key. (Actually, some keys can be longer
# than L characters, but they always start with L digits.) The keys
# cover all integers between 1 and N. Whenever an entry is added to
# the foreground it is removed form the background and vice versa.
set key [btree_key $::c4]
if {[scan $key %d k]<1} {set k 0}
if {$k!=$i} {
- # puts "MISSING $i"
- # puts {Page 3:}; btree_page_dump $::b 3
- # puts {Page 4:}; btree_page_dump $::b 4
- # exit
return "Key $i is missing from both foreground and background"
}
set data [btree_data $::c4]
}
}
+# Look at all elements in both the foreground and background tables.
+# Make sure the key is always the same as the prefix of the data.
+#
+# This routine was used for hunting bugs. It is not a part of standard
+# tests.
+#
+proc check_data {n key} {
+ global c3 c4
+ incr n -1
+ foreach c [list $c3 $c4] {
+ btree_first $c ;# move_to $c $key
+ set cnt 0
+ while {![btree_eof $c]} {
+ set key [btree_key $c]
+ set data [btree_data $c]
+ if {[string range $key 0 $n] ne [string range $data 0 $n]} {
+ puts "key=[list $key] data=[list $data] n=$n"
+ puts "cursor info = [btree_cursor_info $c]"
+ btree_page_dump $::b [lindex [btree_cursor_info $c] 0]
+ exit
+ }
+ btree_next $c
+ }
+ }
+}
+
# Make random changes to the database such that each change preserves
# the invariants. The number of changes is $n*N where N is the parameter
# from the descriptor table. Each changes begins with a random key.
}
}
}
+set btree_trace 0
# Repeat this test sequence on database of various sizes
#
set ::c4 [btree_cursor $::b 4 1]
set ::c5 [btree_cursor $::b 5 1]
set ::c6 [btree_cursor $::b 6 1]
-#if {$testid=="btree2-3.8.4"} {set btree_trace 1}
do_test $testid.5 [subst {
random_changes $n $I $K $D
}] {}