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

The btree.c module compiles and links and passes some tests. Many tests

still fail, though. (CVS 1321)

FossilOrigin-Name: d394b2b217d4d728f9eba397262bf9d36195719e
This commit is contained in:
drh
2004-05-07 17:57:49 +00:00
parent a34b676483
commit de64713041
8 changed files with 225 additions and 182 deletions

View File

@ -1,5 +1,5 @@
C New\sbtree.c\smodule\scompiles\sand\slinks.\s(CVS\s1320)
D 2004-05-07T13:30:42
C The\sbtree.c\smodule\scompiles\sand\slinks\sand\spasses\ssome\stests.\s\sMany\stests\nstill\sfail,\sthough.\s(CVS\s1321)
D 2004-05-07T17:57:50
F Makefile.in ab7b0d5118e2da97bac66be8684a1034e3500f5a
F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
@ -23,7 +23,7 @@ F sqlite.def fc4f5734786fe4743cfe2aa98eb2da4b089edb5f
F sqlite.pc.in 30552343140c53304c2a658c080fbe810cd09ca2
F src/attach.c b01db0d3211f673d8e670abf7eaad04591d40d14
F src/auth.c 4fa3b05bd19445d1c474d6751c4a508d6ea0abe1
F src/btree.c 4c4ccf85d2852aa85c5d6ec7b34b047e363c0366
F src/btree.c ff2f51fcd01c4fb9f2ce0f061a549e0c9aae9d74
F src/btree.h 49b255b2880c50a3572a536ea935edb2dd33aae3
F src/btree_rb.c 99feb3ff835106d018a483a1ce403e5cf9c718bc
F src/build.c 76fbca30081decd6615dee34b48c927ed5063752
@ -40,7 +40,7 @@ F src/main.c 94dd355768e2a389e184a069b6880f4bac100307
F src/md5.c c53e7b50418afbde22d07128baf3cc615530e846
F src/os.c 5f11382733805d4529ec2a30800e117f30995ea8
F src/os.h 250a3789be609adfee5c5aa20137ce8683276f24
F src/pager.c 2e3af839e7aab5bfaff7a0ef4694bae487b0ffeb
F src/pager.c d18d56247c40bf4006ca7761c457b7d76af5c62a
F src/pager.h 138ca7f73c47bebf469591939dcefa934cdf8d26
F src/parse.y 023720cb8c3bef74e51738bca78335d0dc6d2cfd
F src/pragma.c f9c157b0591419d2d3407dac90222020d2a6d822
@ -51,10 +51,10 @@ F src/shell.c 920af040d3a33ea8919c82cee45b424ad841cee0
F src/sqlite.h.in 35bec264dfb4965bbfeb7e75221f8658f210c30d
F src/sqliteInt.h 44a17815ec6ffb93151723aa5cde7263162f52f3
F src/table.c d845cb101b5afc1f7fea083c99e3d2fa7998d895
F src/tclsqlite.c 3a5f8192ed5279a68610102a92a3a9f0cdd09e68
F src/tclsqlite.c 9fe6fc0c20820e9411dfea407635de9b9d3ae0e3
F src/test1.c 9aa62b89d420e6763b5e7ae89a47f6cf87370477
F src/test2.c 9d611c45e1b07039a2bd95f5ea73178362b23229
F src/test3.c 0b62d371f43bdb8fb1e3d5c4863743d6729f4e80
F src/test3.c d6af4e26bdbb7512ab5d01e49f34e72415d58a3b
F src/test4.c 6e3e31acfaf21d66420fc35fda5b17dc0000cc8d
F src/test5.c 3ff0565057b8d23e20092d5c6c0b7cb0d932c51e
F src/tokenize.c 6676b946fd8825b67ab52140af4fdc57a70bda48
@ -75,7 +75,7 @@ F test/auth.test 5c4d95cdaf539c0c236e20ce1f71a93e7dde9185
F test/bigfile.test ea904b853ce2d703b16c5ce90e2b54951bc1ae81
F test/bigrow.test 8ab252dba108f12ad64e337b0f2ff31a807ac578
F test/bind.test 56a57043b42c4664ca705f6050e56717a8a6699a
F test/btree.test 677aeaac7b7b81980b446ca9cab15aa0cc5550d5
F test/btree.test 77f93efac02dd05c7532b366b226bfe74757af57
F test/btree2.test e3b81ec33dc2f89b3e6087436dfe605b870c9080
F test/btree3.test e597fb59be2ac0ea69c62aaa2064e998e528b665
F test/btree3rb.test 127efcf5cdfcc352054e7db12622b01cdd8b36ac
@ -135,7 +135,7 @@ F test/table.test 371a1fc1c470982b2f68f9732f903a5d96f949c4
F test/tableapi.test e0c4cce61e58343caa84dab33fa6823cb35fe1e1
F test/tclsqlite.test a684fc191b81e6cded8a81263663d5a130fbb013
F test/temptable.test a770ba6308d7f7332fce985086b8e06bed6430c2
F test/tester.tcl 5b47e21f442fe8afae963bc45beb54795cf5d162
F test/tester.tcl 64babe2528dec64125ddc8c1af763713710b59c3
F test/thread1.test 53f050d5be6932d9430df7756edd379366508ff6
F test/threadtest1.c f7f896e62ed46feae1dc411114a48c15a0f82ee2
F test/threadtest2.c d94ca4114fd1504f7e0ae724bcd83d4b40931d86
@ -190,7 +190,7 @@ F www/sqlite.tcl 3c83b08cf9f18aa2d69453ff441a36c40e431604
F www/tclsqlite.tcl b9271d44dcf147a93c98f8ecf28c927307abd6da
F www/vdbe.tcl 9b9095d4495f37697fd1935d10e14c6015e80aa1
F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4
P 7fd1a660b0607b7c36de1278724521cbea72af0c
R e634acb38b6d10c4d5783a02c4f65e26
P dcd6b55f932a7ade4ad058534651e198b56370ad
R cdb403059e0209ca0544e8ccaa4370da
U drh
Z a193f9bb2598a024f21bcc3c2eb519e6
Z 48eb767d5af5b72432055086442dfd47

View File

@ -1 +1 @@
dcd6b55f932a7ade4ad058534651e198b56370ad
d394b2b217d4d728f9eba397262bf9d36195719e

View File

@ -9,7 +9,7 @@
** May you share freely, never taking more than you give.
**
*************************************************************************
** $Id: btree.c,v 1.110 2004/05/07 13:30:42 drh Exp $
** $Id: btree.c,v 1.111 2004/05/07 17:57:50 drh Exp $
**
** This file implements a external (disk-based) database using BTrees.
** For a detailed discussion of BTrees, refer to
@ -57,7 +57,7 @@
** of that header is as follows:
**
** OFFSET SIZE DESCRIPTION
** 0 16 Header string: "SQLite version 3"
** 0 16 Header string: "SQLite format 3\000"
** 16 2 Page size in bytes.
** 18 1 File format write version
** 19 1 File format read version
@ -187,16 +187,16 @@ typedef struct MemPage MemPage;
/*
** This is a magic string that appears at the beginning of every
** SQLite database in order to identify the file as a real database.
** 0123456789 123456 */
static const char zMagicHeader[] = "SQLite version 3";
** 123456789 123456 */
static const char zMagicHeader[] = "SQLite format 3";
/*
** Page type flags. An ORed combination of these flags appear as the
** first byte of every BTree page.
*/
#define PTF_LEAF 0x01
#define PTF_INTKEY 0x01
#define PTF_ZERODATA 0x02
#define PTF_INTKEY 0x04
#define PTF_LEAF 0x04
/* Idea for the future: PTF_LEAFDATA */
/*
@ -210,6 +210,7 @@ static const char zMagicHeader[] = "SQLite version 3";
** The pageDestructor() routine handles that chore.
*/
struct MemPage {
u32 notUsed;
struct Btree *pBt; /* Pointer back to BTree structure */
unsigned char *aData; /* Pointer back to the start of the page */
u8 isInit; /* True if previously initialized */
@ -326,10 +327,10 @@ static unsigned int getVarint(unsigned char *p, u64 *pResult){
static unsigned int putVarint(unsigned char *p, u64 v){
int i = 0;
do{
p[i++] = v & 0x7f;
p[i++] = (v & 0x7f) | 0x80;
v >>= 7;
}while( v!=0 );
p[i-1] |= 0x80;
p[i-1] &= 0x7f;
return i;
}
@ -354,7 +355,7 @@ static void parseCellHeader(
}else{
n += getVarint(&pCell[n], pnData);
}
n += getVarint(pCell, pnKey);
n += getVarint(&pCell[n], pnKey);
*pnHeader = n;
}
@ -489,9 +490,10 @@ static int allocateSpace(MemPage *pPage, int nByte){
assert( pc>0 && size>=nByte );
assert( pc+size<=pPage->pBt->pageSize );
if( size>nByte+4 ){
put2byte(&data[addr], pc+nByte);
put2byte(&data[pc+size], get2byte(&data[pc]));
put2byte(&data[pc+size+2], size-nByte);
int newStart = pc+nByte;
put2byte(&data[addr], newStart);
put2byte(&data[newStart], get2byte(&data[pc]));
put2byte(&data[newStart+2], size-nByte);
}else{
put2byte(&data[addr], get2byte(&data[pc]));
data[hdr+5] += size-nByte;
@ -691,7 +693,7 @@ static int initPage(
assert( pPage->pBt!=0 );
assert( pParent==0 || pParent->pBt==pPage->pBt );
assert( pPage->pgno==sqlite3pager_pagenumber(pPage->aData) );
assert( pPage->aData == &((unsigned char*)pPage)[pPage->pBt->pageSize] );
assert( pPage->aData == &((unsigned char*)pPage)[-pPage->pBt->pageSize] );
assert( pPage->isInit==0 || pPage->pParent==pParent );
if( pPage->isInit ) return SQLITE_OK;
assert( pPage->pParent==0 );
@ -700,7 +702,8 @@ static int initPage(
sqlite3pager_ref(pParent->aData);
}
pPage->nCell = pPage->nCellAlloc = 0;
pPage->hdrOffset = hdr = pPage->pgno==1 ? 100 : 0;
assert( pPage->hdrOffset==(pPage->pgno==1 ? 100 : 0) );
hdr = pPage->hdrOffset;
data = pPage->aData;
c = data[hdr];
pPage->intKey = (c & PTF_INTKEY)!=0;
@ -722,8 +725,8 @@ static int initPage(
pc = get2byte(&data[hdr+3]);
for(i=0; pc>0; i++){
pPage->aCell[i] = &data[pc];
pc = get2byte(&data[pc]);
sumCell += cellSize(pPage, &data[pc]);
pc = get2byte(&data[pc]);
}
/* Compute the total free space on the page */
@ -746,6 +749,7 @@ static int initPage(
return SQLITE_CORRUPT;
}
pPage->isInit = 1;
return SQLITE_OK;
}
@ -762,12 +766,13 @@ static void zeroPage(MemPage *pPage, int flags){
assert( sqlite3pager_iswriteable(data) );
memset(&data[hdr], 0, pBt->pageSize - hdr);
data[hdr] = flags;
first = hdr + 6 + 4*((flags&0x01)!=0);
first = hdr + 6 + 4*((flags&PTF_LEAF)==0);
put2byte(&data[hdr+1], first);
put2byte(&data[first+2], pBt->pageSize - first);
sqliteFree(pPage->aCell);
pPage->aCell = 0;
pPage->nCell = 0;
pPage->nCellAlloc = 0;
pPage->nFree = pBt->pageSize - first;
pPage->intKey = (flags & PTF_INTKEY)!=0;
pPage->leaf = (flags & PTF_LEAF)!=0;
@ -789,10 +794,30 @@ static int getPage(Btree *pBt, Pgno pgno, MemPage **ppPage){
pPage->aData = aData;
pPage->pBt = pBt;
pPage->pgno = pgno;
pPage->hdrOffset = pPage->pgno==1 ? 100 : 0;
*ppPage = pPage;
return SQLITE_OK;
}
/*
** Get a page from the pager and initialize it. This routine
** is just a convenience wrapper around separate calls to
** getPage() and initPage().
*/
static int getAndInitPage(
Btree *pBt, /* The database file */
Pgno pgno, /* Number of the page to get */
MemPage **ppPage, /* Write the page pointer here */
MemPage *pParent /* Parent of the page */
){
int rc;
rc = getPage(pBt, pgno, ppPage);
if( rc==SQLITE_OK ){
rc = initPage(*ppPage, pParent);
}
return rc;
}
/*
** Release a MemPage. This should be called once for each prior
** call to getPage.
@ -988,7 +1013,7 @@ static int newDatabase(Btree *pBt){
MemPage *pP1;
unsigned char *data;
int rc;
if( sqlite3pager_pagecount(pBt->pPager)>1 ) return SQLITE_OK;
if( sqlite3pager_pagecount(pBt->pPager)>0 ) return SQLITE_OK;
pP1 = pBt->pPage1;
assert( pP1!=0 );
data = pP1->aData;
@ -1231,11 +1256,7 @@ int sqlite3BtreeCursor(
goto create_cursor_exception;
}
pCur->pgnoRoot = (Pgno)iTable;
rc = getPage(pBt, pCur->pgnoRoot, &pCur->pPage);
if( rc!=SQLITE_OK ){
goto create_cursor_exception;
}
rc = initPage(pCur->pPage, 0);
rc = getAndInitPage(pBt, pCur->pgnoRoot, &pCur->pPage, 0);
if( rc!=SQLITE_OK ){
goto create_cursor_exception;
}
@ -1338,7 +1359,7 @@ int sqlite3BtreeKeySize(BtCursor *pCur, u64 *pSize){
}else{
unsigned char *cell = pPage->aCell[pCur->idx];
cell += 2; /* Skip the offset to the next cell */
if( pPage->leaf ){
if( !pPage->leaf ){
cell += 4; /* Skip the child pointer */
}
if( !pPage->zeroData ){
@ -1378,7 +1399,7 @@ static int getPayload(
assert( pCur->idx>=0 && pCur->idx<pPage->nCell );
aPayload = pPage->aCell[pCur->idx];
aPayload += 2; /* Skip the next cell index */
if( pPage->leaf ){
if( !pPage->leaf ){
aPayload += 4; /* Skip the child pointer */
}
if( pPage->zeroData ){
@ -1497,7 +1518,7 @@ void *sqlite3BtreeKeyFetch(BtCursor *pCur){
assert( pCur->idx>=0 && pCur->idx<pPage->nCell );
aPayload = pPage->aCell[pCur->idx];
aPayload += 2; /* Skip the next cell index */
if( pPage->leaf ){
if( !pPage->leaf ){
aPayload += 4; /* Skip the child pointer */
}
if( !pPage->zeroData ){
@ -1530,7 +1551,7 @@ int sqlite3BtreeDataSize(BtCursor *pCur, u32 *pSize){
u64 size;
cell = pPage->aCell[pCur->idx];
cell += 2; /* Skip the offset to the next cell */
if( pPage->leaf ){
if( !pPage->leaf ){
cell += 4; /* Skip the child pointer */
}
getVarint(cell, &size);
@ -1572,9 +1593,7 @@ static int moveToChild(BtCursor *pCur, u32 newPgno){
MemPage *pOldPage;
Btree *pBt = pCur->pBt;
rc = getPage(pBt, newPgno, &pNewPage);
if( rc ) return rc;
rc = initPage(pNewPage, pCur->pPage);
rc = getAndInitPage(pBt, newPgno, &pNewPage, pCur->pPage);
if( rc ) return rc;
pNewPage->idxParent = pCur->idx;
pOldPage = pCur->pPage;
@ -1600,7 +1619,7 @@ static int moveToChild(BtCursor *pCur, u32 newPgno){
static int isRootPage(MemPage *pPage){
MemPage *pParent = pPage->pParent;
assert( pParent==0 || pParent->isInit );
if( pParent || (pParent->pgno==1 && pParent->nCell==0) ) return 1;
if( pParent==0 || (pParent->pgno==1 && pParent->nCell==0) ) return 1;
return 0;
}
@ -1666,9 +1685,7 @@ static int moveToRoot(BtCursor *pCur){
int rc;
Btree *pBt = pCur->pBt;
rc = getPage(pBt, pCur->pgnoRoot, &pRoot);
if( rc ) return rc;
rc = initPage(pRoot, 0);
rc = getAndInitPage(pBt, pCur->pgnoRoot, &pRoot, 0);
if( rc ) return rc;
releasePage(pCur->pPage);
pCur->pPage = pRoot;
@ -1807,7 +1824,7 @@ int sqlite3BtreeMoveto(BtCursor *pCur, const void *pKey, u64 nKey, int *pRes){
void *pCellKey;
u64 nCellKey;
pCur->idx = (lwr+upr)/2;
nCellKey = sqlite3BtreeKeySize(pCur, &nCellKey);
sqlite3BtreeKeySize(pCur, &nCellKey);
if( pPage->intKey ){
if( nCellKey<nKey ){
c = -1;
@ -2211,6 +2228,7 @@ static int fillInCell(
if( n>nSrc ) n = nSrc;
memcpy(pPayload, pSrc, n);
nPayload -= n;
pPayload += n;
nSrc -= n;
spaceLeft -= n;
if( nSrc==0 ){
@ -2285,13 +2303,15 @@ static void reparentChildPages(MemPage *pPage){
** the linked list.
*/
static void dropCell(MemPage *pPage, int idx, int sz){
int j;
int j, pc;
assert( idx>=0 && idx<pPage->nCell );
assert( sz==cellSize(pPage, pPage->aCell[idx]) );
assert( sqlite3pager_iswriteable(pPage->aData) );
assert( pPage->aCell[idx]>=pPage->aData );
assert( pPage->aCell[idx]<&pPage->aData[pPage->pBt->pageSize-sz] );
freeSpace(pPage, idx, sz);
pc = Addr(pPage->aCell[idx]) - Addr(pPage->aData);
assert( pc>pPage->hdrOffset && pc+sz<=pPage->pBt->pageSize );
freeSpace(pPage, pc, sz);
for(j=idx; j<pPage->nCell-1; j++){
pPage->aCell[j] = pPage->aCell[j+1];
}
@ -2344,7 +2364,7 @@ static void relinkCellList(MemPage *pPage){
assert( sqlite3pager_iswriteable(pPage->aData) );
idxFrom = pPage->hdrOffset+3;
for(i=0; i<pPage->nCell; i++){
int idx = Addr(pPage->aCell[i]) - Addr(pPage);
int idx = Addr(pPage->aCell[i]) - Addr(pPage->aData);
assert( idx>pPage->hdrOffset && idx<pPage->pBt->pageSize );
put2byte(&pPage->aData[idxFrom], idx);
idxFrom = idx;
@ -2620,9 +2640,7 @@ static int balance(MemPage *pPage){
}else{
break;
}
rc = getPage(pBt, pgnoOld[i], &apOld[i]);
if( rc ) goto balance_cleanup;
rc = initPage(apOld[i], pParent);
rc = getAndInitPage(pBt, pgnoOld[i], &apOld[i], pParent);
if( rc ) goto balance_cleanup;
apOld[i]->idxParent = k;
apCopy[i] = 0;
@ -3053,7 +3071,7 @@ int sqlite3BtreeCreateTable(Btree *pBt, int *piTable, int flags){
rc = allocatePage(pBt, &pRoot, &pgnoRoot, 0);
if( rc ) return rc;
assert( sqlite3pager_iswriteable(pRoot->aData) );
zeroPage(pRoot, flags);
zeroPage(pRoot, flags | PTF_LEAF);
sqlite3pager_unref(pRoot->aData);
*piTable = (int)pgnoRoot;
return SQLITE_OK;
@ -3074,12 +3092,10 @@ static int clearDatabasePage(
unsigned char *pCell;
int i;
rc = getPage(pBt, pgno, &pPage);
rc = getAndInitPage(pBt, pgno, &pPage, pParent);
if( rc ) return rc;
rc = sqlite3pager_write(pPage->aData);
if( rc ) return rc;
rc = initPage(pPage, pParent);
if( rc ) return rc;
for(i=0; i<pPage->nCell; i++){
pCell = pPage->aCell[i];
if( !pPage->leaf ){
@ -3183,8 +3199,8 @@ int sqlite3BtreeUpdateMeta(Btree *pBt, int idx, u32 iMeta){
if( !pBt->inTrans ){
return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR;
}
rc = sqlite3pager_get(pBt->pPager, 1, (void**)&pP1);
if( rc ) return rc;
assert( pBt->pPage1!=0 );
pP1 = pBt->pPage1->aData;
rc = sqlite3pager_write(pP1);
if( rc ) return rc;
put4byte(&pP1[36 + idx*4], iMeta);
@ -3218,7 +3234,7 @@ int sqlite3BtreePageDump(Btree *pBt, int pgno, int recursive){
printf("PAGE %d: flags=0x%02x frag=%d\n", pgno,
pPage->aData[pPage->hdrOffset], pPage->aData[pPage->hdrOffset+5]);
i = 0;
hdrOffset = pgno==1 ? 100 : 0;
assert( pPage->hdrOffset == (pgno==1 ? 100 : 0) );
idx = get2byte(&pPage->aData[hdrOffset+3]);
while( idx>0 && idx<=pBt->pageSize ){
u64 nData, nKey;

View File

@ -18,7 +18,7 @@
** file simultaneously, or one process from reading the database while
** another is writing.
**
** @(#) $Id: pager.c,v 1.102 2004/04/26 14:10:21 drh Exp $
** @(#) $Id: pager.c,v 1.103 2004/05/07 17:57:50 drh Exp $
*/
#include "os.h" /* Must be first to enable large file support */
#include "sqliteInt.h"
@ -569,7 +569,9 @@ static int pager_playback_one_page(Pager *pPager, OsFile *jfd, int format){
*/
assert( pPg->nRef==0 || pPg->pgno==1 );
memcpy(PGHDR_TO_DATA(pPg), pgRec.aData, SQLITE_PAGE_SIZE);
memset(PGHDR_TO_EXTRA(pPg), 0, pPager->nExtra);
if( pPager->xDestructor ){
pPager->xDestructor(PGHDR_TO_DATA(pPg));
}
pPg->dirty = 0;
pPg->needSync = 0;
CODEC(pPager, PGHDR_TO_DATA(pPg), pPg->pgno, 3);

View File

@ -11,7 +11,7 @@
*************************************************************************
** A TCL Interface to SQLite
**
** $Id: tclsqlite.c,v 1.61 2004/05/06 23:37:53 danielk1977 Exp $
** $Id: tclsqlite.c,v 1.62 2004/05/07 17:57:50 drh Exp $
*/
#ifndef NO_TCL /* Omit this whole file if TCL is unavailable */
@ -1212,7 +1212,7 @@ int TCLSH_MAIN(int argc, char **argv){
extern int Md5_Init(Tcl_Interp*);
/* Sqlitetest1_Init(interp); */
Sqlitetest2_Init(interp);
/* Sqlitetest3_Init(interp); */
Sqlitetest3_Init(interp);
/* Sqlitetest4_Init(interp); */
Sqlitetest5_Init(interp);
Md5_Init(interp);

View File

@ -13,7 +13,7 @@
** is not included in the SQLite library. It is used for automated
** testing of the SQLite library.
**
** $Id: test3.c,v 1.26 2004/05/07 13:30:42 drh Exp $
** $Id: test3.c,v 1.27 2004/05/07 17:57:50 drh Exp $
*/
#include "sqliteInt.h"
#include "pager.h"
@ -329,9 +329,9 @@ static int btree_update_meta(
Btree *pBt;
int rc;
int i;
int aMeta[SQLITE_N_BTREE_META-1];
int aMeta[SQLITE_N_BTREE_META];
if( argc!=2+SQLITE_N_BTREE_META ){
if( argc!=1+SQLITE_N_BTREE_META ){
char zBuf[30];
sprintf(zBuf,"%d",SQLITE_N_BTREE_META);
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
@ -339,11 +339,11 @@ static int btree_update_meta(
return TCL_ERROR;
}
if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR;
for(i=0; i<SQLITE_N_BTREE_META-1; i++){
if( Tcl_GetInt(interp, argv[i+2], &aMeta[i]) ) return TCL_ERROR;
for(i=1; i<SQLITE_N_BTREE_META; i++){
if( Tcl_GetInt(interp, argv[i+1], &aMeta[i]) ) return TCL_ERROR;
}
for(i=0; i<SQLITE_N_BTREE_META-1; i++){
rc = sqlite3BtreeUpdateMeta(pBt, i+1, aMeta[i]);
for(i=1; i<SQLITE_N_BTREE_META; i++){
rc = sqlite3BtreeUpdateMeta(pBt, i, aMeta[i]);
if( rc!=SQLITE_OK ){
Tcl_AppendResult(interp, errorName(rc), 0);
return TCL_ERROR;
@ -594,7 +594,13 @@ static int btree_move_to(
return TCL_ERROR;
}
if( Tcl_GetInt(interp, argv[1], (int*)&pCur) ) return TCL_ERROR;
if( sqlite3BtreeFlags(pCur) & BTREE_INTKEY ){
int iKey;
if( Tcl_GetInt(interp, argv[2], &iKey) ) return TCL_ERROR;
rc = sqlite3BtreeMoveto(pCur, 0, iKey, &res);
}else{
rc = sqlite3BtreeMoveto(pCur, argv[2], strlen(argv[2]), &res);
}
if( rc ){
Tcl_AppendResult(interp, errorName(rc), 0);
return TCL_ERROR;
@ -655,8 +661,14 @@ static int btree_insert(
return TCL_ERROR;
}
if( Tcl_GetInt(interp, argv[1], (int*)&pCur) ) return TCL_ERROR;
if( sqlite3BtreeFlags(pCur) & BTREE_INTKEY ){
int iKey;
if( Tcl_GetInt(interp, argv[2], &iKey) ) return TCL_ERROR;
rc = sqlite3BtreeInsert(pCur, 0, iKey, argv[3], strlen(argv[3]));
}else{
rc = sqlite3BtreeInsert(pCur, argv[2], strlen(argv[2]),
argv[3], strlen(argv[3]));
}
if( rc ){
Tcl_AppendResult(interp, errorName(rc), 0);
return TCL_ERROR;
@ -855,11 +867,8 @@ static int btree_key(
}else{
zBuf = malloc( n+1 );
rc = sqlite3BtreeKey(pCur, 0, n, zBuf);
if( rc!=n ){
char zMsg[100];
free(zBuf);
sprintf(zMsg, "truncated key: got %d of %llu bytes", rc, n);
Tcl_AppendResult(interp, zMsg, 0);
if( rc ){
Tcl_AppendResult(interp, errorName(rc), 0);
return TCL_ERROR;
}
zBuf[n] = 0;
@ -894,11 +903,8 @@ static int btree_data(
sqlite3BtreeDataSize(pCur, &n);
zBuf = malloc( n+1 );
rc = sqlite3BtreeData(pCur, 0, n, zBuf);
if( rc!=n ){
char zMsg[100];
free(zBuf);
sprintf(zMsg, "truncated data: got %d of %u bytes", rc, n);
Tcl_AppendResult(interp, zMsg, 0);
if( rc ){
Tcl_AppendResult(interp, errorName(rc), 0);
return TCL_ERROR;
}
zBuf[n] = 0;

View File

@ -11,21 +11,18 @@
# This file implements regression tests for SQLite library. The
# focus of this script is btree database backend
#
# $Id: btree.test,v 1.15 2004/02/10 01:54:28 drh Exp $
# $Id: btree.test,v 1.16 2004/05/07 17:57:50 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
if {[info commands btree_open]!="" && $SQLITE_PAGE_SIZE==1024
&& $SQLITE_USABLE_SIZE==1024} {
# 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]
set rc [catch {btree_open test1.bt 2000 0} ::b1]
} {0}
# The second element of the list returned by btree_pager_stats is the
@ -38,7 +35,7 @@ do_test btree-1.1.1 {
lindex [btree_pager_stats $::b1] 1
} {0}
do_test btree-1.2 {
set rc [catch {btree_open test1.bt} ::b2]
set rc [catch {btree_open test1.bt 2000 0} ::b2]
} {0}
do_test btree-1.3 {
set rc [catch {btree_close $::b2} msg]
@ -55,17 +52,18 @@ do_test btree-1.4.1 {
lindex [btree_pager_stats $::b1] 1
} {1}
do_test btree-1.5 {
set rc [catch {btree_cursor $::b1 2 1} ::c1]
set rc [catch {btree_cursor $::b1 1 1} ::c1]
if {$rc} {lappend rc $::c1}
set rc
} {0}
do_test btree-1.6 {
set rc [catch {btree_insert $::c1 one 1.00} msg]
set rc [catch {btree_insert $::c1 100 1.00} msg]
lappend rc $msg
} {0 {}}
do_test btree-1.7 {
btree_move_to $::c1 100
btree_key $::c1
} {one}
} {100}
do_test btree-1.8 {
btree_data $::c1
} {1.00}
@ -79,7 +77,7 @@ do_test btree-1.10 {
} {0 {}}
do_test btree-1.11 {
file size test1.bt
} {2048}
} {1024}
do_test btree-1.12 {
lindex [btree_pager_stats $::b1] 1
} {0}
@ -87,105 +85,110 @@ do_test btree-1.12 {
# Reopen the database and attempt to read the record that we wrote.
#
do_test btree-2.1 {
set rc [catch {btree_cursor $::b1 2 1} ::c1]
set rc [catch {btree_cursor $::b1 1 1} ::c1]
if {$rc} {lappend rc $::c1}
set rc
} {0}
do_test btree-2.2 {
btree_move_to $::c1 abc
btree_move_to $::c1 99
} {1}
do_test btree-2.3 {
btree_move_to $::c1 xyz
btree_move_to $::c1 101
} {-1}
do_test btree-2.4 {
btree_move_to $::c1 one
btree_move_to $::c1 100
} {0}
do_test btree-2.5 {
btree_key $::c1
} {one}
} {100}
do_test btree-2.6 {
btree_data $::c1
} {1.00}
do_test btree-2.7 {
lindex [btree_pager_stats $::b1] 1
} {2}
} {1}
# Do some additional inserts
#
do_test btree-3.1 {
btree_begin_transaction $::b1
btree_insert $::c1 two 2.00
btree_insert $::c1 200 2.00
btree_move_to $::c1 200
btree_key $::c1
} {two}
} {200}
do_test btree-3.1.1 {
lindex [btree_pager_stats $::b1] 1
} {2}
} {1}
do_test btree-3.2 {
btree_insert $::c1 three 3.00
btree_insert $::c1 300 3.00
btree_move_to $::c1 300
btree_key $::c1
} {three}
} {300}
do_test btree-3.4 {
btree_insert $::c1 four 4.00
btree_insert $::c1 400 4.00
btree_move_to $::c1 400
btree_key $::c1
} {four}
} {400}
do_test btree-3.5 {
btree_insert $::c1 five 5.00
btree_insert $::c1 500 5.00
btree_move_to $::c1 500
btree_key $::c1
} {five}
} {500}
do_test btree-3.6 {
btree_insert $::c1 six 6.00
btree_insert $::c1 600 6.00
btree_move_to $::c1 600
btree_key $::c1
} {six}
} {600}
#btree_page_dump $::b1 2
do_test btree-3.7 {
set rc [btree_move_to $::c1 {}]
set rc [btree_move_to $::c1 0]
expr {$rc>0}
} {1}
do_test btree-3.8 {
btree_key $::c1
} {five}
} {100}
do_test btree-3.9 {
btree_data $::c1
} {5.00}
} {1.00}
do_test btree-3.10 {
btree_next $::c1
btree_key $::c1
} {four}
} {200}
do_test btree-3.11 {
btree_data $::c1
} {4.00}
} {2.00}
do_test btree-3.12 {
btree_next $::c1
btree_key $::c1
} {one}
} {300}
do_test btree-3.13 {
btree_data $::c1
} {1.00}
} {3.00}
do_test btree-3.14 {
btree_next $::c1
btree_key $::c1
} {six}
} {400}
do_test btree-3.15 {
btree_data $::c1
} {6.00}
} {4.00}
do_test btree-3.16 {
btree_next $::c1
btree_key $::c1
} {three}
} {500}
do_test btree-3.17 {
btree_data $::c1
} {3.00}
} {5.00}
do_test btree-3.18 {
btree_next $::c1
btree_key $::c1
} {two}
} {600}
do_test btree-3.19 {
btree_data $::c1
} {2.00}
} {6.00}
do_test btree-3.20 {
btree_next $::c1
btree_key $::c1
} {}
} {0}
do_test btree-3.21 {
btree_data $::c1
} {}
@ -208,182 +211,188 @@ do_test btree-3.23.1 {
} {0}
do_test btree-3.24 {
file size test1.bt
} {2048}
} {1024}
do_test btree-3.25 {
set rc [catch {btree_cursor $::b1 2 1} ::c1]
set rc [catch {btree_cursor $::b1 1 1} ::c1]
if {$rc} {lappend rc $::c1}
set rc
} {0}
do_test btree-3.25.1 {
lindex [btree_pager_stats $::b1] 1
} {2}
} {1}
do_test btree-3.26 {
set rc [btree_move_to $::c1 {}]
set rc [btree_move_to $::c1 0]
expr {$rc>0}
} {1}
do_test btree-3.27 {
btree_key $::c1
} {five}
} {100}
do_test btree-3.28 {
btree_data $::c1
} {5.00}
} {1.00}
do_test btree-3.29 {
btree_next $::c1
btree_key $::c1
} {four}
} {200}
do_test btree-3.30 {
btree_data $::c1
} {4.00}
} {2.00}
do_test btree-3.31 {
btree_next $::c1
btree_key $::c1
} {one}
} {300}
do_test btree-3.32 {
btree_data $::c1
} {1.00}
} {3.00}
do_test btree-3.33 {
btree_next $::c1
btree_key $::c1
} {six}
} {400}
do_test btree-3.34 {
btree_data $::c1
} {6.00}
} {4.00}
do_test btree-3.35 {
btree_next $::c1
btree_key $::c1
} {three}
} {500}
do_test btree-3.36 {
btree_data $::c1
} {3.00}
} {5.00}
do_test btree-3.37 {
btree_next $::c1
btree_key $::c1
} {two}
} {600}
do_test btree-3.38 {
btree_data $::c1
} {2.00}
} {6.00}
do_test btree-3.39 {
btree_next $::c1
btree_key $::c1
} {}
} {0}
do_test btree-3.40 {
btree_data $::c1
} {}
do_test btree-3.41 {
lindex [btree_pager_stats $::b1] 1
} {2}
} {1}
# Now try a delete
#
do_test btree-4.1 {
btree_begin_transaction $::b1
btree_move_to $::c1 one
btree_move_to $::c1 100
btree_key $::c1
} {one}
} {100}
do_test btree-4.1.1 {
lindex [btree_pager_stats $::b1] 1
} {2}
} {1}
do_test btree-4.2 {
btree_delete $::c1
} {}
do_test btree-4.3 {
btree_move_to $::c1 100
btree_key $::c1
} {six}
} {200}
do_test btree-4.4 {
btree_next $::c1
btree_key $::c1
} {six}
} {300}
do_test btree-4.5 {
btree_next $::c1
btree_key $::c1
} {three}
} {400}
do_test btree-4.4 {
btree_move_to $::c1 {}
btree_move_to $::c1 0
set r {}
while 1 {
set key [btree_key $::c1]
if {$key==""} break
if {$key==0} 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}
} {200 2.00 300 3.00 400 4.00 500 5.00 600 6.00}
# Commit and make sure the delete is still there.
#
do_test btree-4.5 {
btree_commit $::b1
btree_move_to $::c1 {}
btree_move_to $::c1 0
set r {}
while 1 {
set key [btree_key $::c1]
if {$key==""} break
if {$key==0} 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}
} {200 2.00 300 3.00 400 4.00 500 5.00 600 6.00}
# Completely close the database and reopen it. Then check
# the data again.
#
do_test btree-4.6 {
lindex [btree_pager_stats $::b1] 1
} {2}
} {1}
do_test btree-4.7 {
btree_close_cursor $::c1
lindex [btree_pager_stats $::b1] 1
} {0}
do_test btree-4.8 {
btree_close $::b1
set ::b1 [btree_open test1.bt]
set ::c1 [btree_cursor $::b1 2 1]
set ::b1 [btree_open test1.bt 2000 0]
set ::c1 [btree_cursor $::b1 1 1]
lindex [btree_pager_stats $::b1] 1
} {2}
} {1}
do_test btree-4.9 {
set r {}
btree_first $::c1
while 1 {
set key [btree_key $::c1]
if {$key==""} break
if {$key==0} 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}
} {200 2.00 300 3.00 400 4.00 500 5.00 600 6.00}
# Try to read and write meta data
#
do_test btree-5.1 {
btree_get_meta $::b1
} {0 0 0 0 0 0 0 0 0 0}
} {0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0}
do_test btree-5.2 {
set rc [catch {btree_update_meta $::b1 1 2 3 4 5 6 7 8 9 10} msg]
set rc [catch {
btree_update_meta $::b1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
} msg]
lappend rc $msg
} {1 SQLITE_ERROR}
do_test btree-5.3 {
btree_begin_transaction $::b1
set rc [catch {btree_update_meta $::b1 1 2 3 4 5 6 7 8 9 10} msg]
set rc [catch {
btree_update_meta $::b1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
} msg]
lappend rc $msg
} {0 {}}
do_test btree-5.4 {
btree_get_meta $::b1
} {0 2 3 4 5 6 7 8 9 10}
} {0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15}
do_test btree-5.5 {
btree_close_cursor $::c1
btree_rollback $::b1
btree_get_meta $::b1
} {0 0 0 0 0 0 0 0 0 0}
} {0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0}
do_test btree-5.6 {
btree_begin_transaction $::b1
btree_update_meta $::b1 999 10 20 30 40 50 60 70 80 90
btree_update_meta $::b1 10 20 30 40 50 60 70 80 90 100 110 120 130 \
140 150
btree_commit $::b1
btree_get_meta $::b1
} {0 10 20 30 40 50 60 70 80 90}
} {0 10 20 30 40 50 60 70 80 90 100 110 120 130 140 150}
proc select_all {cursor} {
set r {}
@ -397,6 +406,18 @@ proc select_all {cursor} {
}
return $r
}
proc select_all_intkey {cursor} {
set r {}
btree_move_to $cursor 0
while 1 {
set key [btree_key $cursor]
if {$key==0} break
lappend r $key
lappend r [btree_data $cursor]
btree_next $cursor
}
return $r
}
proc select_keys {cursor} {
set r {}
btree_move_to $cursor {}
@ -412,13 +433,13 @@ proc select_keys {cursor} {
# Try to create a new table in the database file
#
do_test btree-6.1 {
set rc [catch {btree_create_table $::b1} msg]
set rc [catch {btree_create_table $::b1 0} msg]
lappend rc $msg
} {1 SQLITE_ERROR}
do_test btree-6.2 {
btree_begin_transaction $::b1
set ::t2 [btree_create_table $::b1]
} {3}
set ::t2 [btree_create_table $::b1 0]
} {2}
do_test btree-6.2.1 {
lindex [btree_pager_stats $::b1] 1
} {1}
@ -432,12 +453,12 @@ do_test btree-6.2.3 {
} {ten}
do_test btree-6.3 {
btree_commit $::b1
set ::c1 [btree_cursor $::b1 2 1]
set ::c1 [btree_cursor $::b1 1 1]
lindex [btree_pager_stats $::b1] 1
} {3}
} {2}
do_test btree-6.3.1 {
select_all $::c1
} {five 5.00 four 4.00 six 6.00 three 3.00 two 2.00}
select_all_intkey $::c1
} {200 2.00 300 3.00 400 4.00 500 5.00 600 6.00}
#btree_page_dump $::b1 3
do_test btree-6.4 {
select_all $::c2
@ -453,7 +474,7 @@ do_test btree-6.6 {
} {}
do_test btree-6.6.1 {
lindex [btree_pager_stats $::b1] 1
} {2}
} {1}
do_test btree-6.7 {
btree_drop_table $::b1 $::t2
} {}
@ -461,15 +482,15 @@ do_test btree-6.7.1 {
lindex [btree_get_meta $::b1] 0
} {1}
do_test btree-6.8 {
set ::t2 [btree_create_table $::b1]
} {3}
set ::t2 [btree_create_table $::b1 0]
} {2}
do_test btree-6.8.1 {
lindex [btree_get_meta $::b1] 0
} {0}
do_test btree-6.9 {
set ::c2 [btree_cursor $::b1 $::t2 1]
lindex [btree_pager_stats $::b1] 1
} {3}
} {2}
do_test btree-6.9.1 {
btree_move_to $::c2 {}
@ -632,7 +653,7 @@ do_test btree-8.8 {
do_test btree-8.9 {
btree_close_cursor $::c1
btree_close $::b1
set ::b1 [btree_open test1.bt]
set ::b1 [btree_open test1.bt 2000 0]
set ::c1 [btree_cursor $::b1 2 1]
btree_move_to $::c1 020
btree_data $::c1
@ -1015,6 +1036,4 @@ do_test btree-99.1 {
catch {unset data}
catch {unset key}
} ;# end if( not mem: and has pager_open command );
finish_test

View File

@ -11,7 +11,7 @@
# This file implements some common TCL routines used for regression
# testing the SQLite library
#
# $Id: tester.tcl,v 1.29 2004/04/26 14:10:22 drh Exp $
# $Id: tester.tcl,v 1.30 2004/05/07 17:57:50 drh Exp $
if 0 {
# Make sure tclsqlite was compiled correctly. Abort now with an
@ -110,7 +110,7 @@ proc do_test {name cmd expected} {
puts "\nExpected: \[$expected\]\n Got: \[$result\]"
incr nErr
lappend ::failList $name
if {$nErr>100} {puts "*** Giving up..."; finalize_testing}
if {$nErr>=1} {puts "*** Giving up..."; finalize_testing}
} else {
puts " Ok"
}