-C Improved\sdocumentation\sof\ssqlite3_blob_open().\s(CVS\s4910)
-D 2008-03-24T12:51:46
+C Removed\sthe\sdirect\sbtree\stests\s-\spart\sof\sthe\songoing\seffort\sto\stest\sby\ncalling\sonly\spublic\sinterfaces.\s\sModify\sthe\ssqlite3VdbeRecordCompare\ninterface\sto\sused\sa\spre-parsed\ssecond\skey\s-\sresulting\sin\sa\s13%\nperformance\simprovement\son\sspeed1p.test.\s(CVS\s4911)
+D 2008-03-25T00:22:21
F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7
F Makefile.in cf434ce8ca902e69126ae0f94fc9f7dc7428a5fa
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
F src/auth.c c8b2ab5c8bad4bd90ed7c294694f48269162c627
F src/bitvec.c 49817d442e51e4123585f3cf3c2afc293a3c91e2
F src/btmutex.c 483ced3c52205b04b97df69161fadbf87f4f1ea2
-F src/btree.c 15424f41344ad96ab56a3322f5930cfb7a8ee24e
-F src/btree.h 19dcf5ad23c17b98855da548e9a8e3eb4429d5eb
-F src/btreeInt.h d7d2f4d9d7f2e72c455326d48b2b478b842a81f6
+F src/btree.c 984962aa403be49d79784f01cc9887d16cd841ed
+F src/btree.h ca065a5910e6dd3b91b88ff9d729450a8b8eda1f
+F src/btreeInt.h c2deca3e778e2a1e6196343b8087a868f4faa19a
F src/build.c 31ed5af4e8ac40c30bb0f88d7fec75e72cc16e0e
F src/callback.c 77b302b0d41468dcda78c70e706e5b84577f0fa0
F src/complete.c 4cf68fd75d60257524cbe74f87351b9848399131
F src/pager.h b1e2258f03878c14b06a95bfa362e8c5c9638170
F src/parse.y b0ee84d94218046ea88c2a6561005710d127ca7d
F src/pragma.c f64eed914518c28d1863356163dea1e6f58e28f2
-F src/prepare.c 1b71b5d43ba3d88f2d3c2a6d084f28ac209df956
+F src/prepare.c f7fc2eb7418dcaa63e22b66c5ecf478e658ecd8f
F src/printf.c 05d2b44d7b5b80c8a4a09108ddad9c20e254370d
F src/random.c 2b2db2de4ab491f5a14d3480466f8f4b5a5db74a
F src/select.c 35063b078beafe9aa35344a8ce039210920d7fea
F src/tclsqlite.c d42912617d4734b8f9195416badf5b27e512ded2
F src/test1.c 342a2628310fa709074d979e695a28a3bb570834
F src/test2.c f0808cc643528b9620e4059ca9bda8346f526121
-F src/test3.c 5c7452038ab27aa698070799b10132f26cdd2a80
+F src/test3.c 9bf750645412effca0b2567b8b833e1e91377b47
F src/test4.c c2c0f5dc907f1346f5d4b65eb5799f11eb9e4071
F src/test5.c 3a6a5717a149d7ca2e6d14f5be72cf7555d54dc4
F src/test6.c 62281c0a9ac0265e579065942f7de4e080f8eb05
F src/utf.c 32b00d6e19010025e58f2ecb2f921d5e126771b4
F src/util.c dba9e04121eb17ec4643d6ca231ff859452cf0e2
F src/vacuum.c 3524411bfb58aac0d87eadd3e5b7cd532772af30
-F src/vdbe.c 43b261f50be60c758430a9072f960715f2ff0852
-F src/vdbe.h 93acc03fe8002173cb6affad2bf5d5c5305ba229
-F src/vdbeInt.h 76c81d057a39813de0fda3cad1498655d53ec69d
+F src/vdbe.c d81771c67e67f9a25af1d53e5c22299becef1322
+F src/vdbe.h 0fef6798be121ed2b5a547a5cb85e0824ec3971f
+F src/vdbeInt.h 4bbec80d55d179ab8438ac9822416d9111638919
F src/vdbeapi.c b9e9d7a58690c1e1ae66de7232edccf4793ad817
-F src/vdbeaux.c 82f3c8913e68b4928de28c3fa117464356d59df6
+F src/vdbeaux.c f3ee532bfdf191f0d2a8c4d1a50816cdd1a235d2
F src/vdbeblob.c 63c750acc7b5012479f508c0e9627372a82cb65d
F src/vdbefifo.c a30c237b2a3577e1415fb6e288cbb6b8ed1e5736
F src/vdbemem.c 67662aac917b627356262f9501591206db2a8845
F test/bindxfer.test 995d2cf8df61204d748cde6960443121c4ccd2e1
F test/bitvec.test 62a512c3f7041d1df12558eb25990e5a19820571
F test/blob.test f2dbdbf1159674283645c2636436839313ee7131
-F test/btree.test d22b1b2cc9becc36f6b1f2f91b9fca1e48060979
-F test/btree2.test 4b56a2a4a4f84d68c77aef271223a713bf5ebafc
-F test/btree4.test 3797b4305694c7af6828675b0f4b1424b8ca30e4
-F test/btree5.test 8e5ff32c02e685d36516c6499add9375fe1377f2
-F test/btree6.test a5ede6bfbbb2ec8b27e62813612c0f28e8f3e027
-F test/btree7.test a6d3b842db22af97dd14b989e90a2fd96066b72f
-F test/btree8.test fadc112bcbd6a0c622d34c813fc8a648eacf8804
-F test/btree9.test 5d8711b241145b90f65dd1795d5dd8290846fa5e
F test/busy.test 76b4887f8b9160ba903c1ac22e8ff406ad6ae2f0
F test/cache.test 3ff445c445742a7b6b9ba6e1d62a25263f9424b9
F test/capi2.test cc64df7560a96f848f919ea2926c60acf639684b
F test/printf.test c3405535b418d454e8a52196a0fc592ec9eec58d
F test/progress.test 5b075c3c790c7b2a61419bc199db87aaf48b8301 x
F test/ptrchng.test 83150cb7b513e33cce90fdc68f4b1817551857c0
-F test/quick.test 037a953ccc4e5419c89528e7b93742db29bc3ec1
+F test/quick.test fcd8fb7aeee4b8bc7a5be56c25104f6f39258eb1
F test/quote.test 215897dbe8de1a6f701265836d6601cc6ed103e6
F test/rdonly.test b34db316525440d3b42c32e83942c02c37d28ef0
F test/reindex.test 38b138abe36bf9a08c791ed44d9f76cd6b97b78b
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
-P a807e7184b857414ce203af129ac1adf2012096c
-R 4101d535e06a9619e1c68b648b338bf6
+P 1ed695f560a58786f2a8467c601f281c67034fd4
+R 4b7a149e165aca7212e2405c0ae3196c
U drh
-Z c87ff7d608d92b0ae8912212b9742706
+Z f27434cb523b0af2e9a84163450beba5
-1ed695f560a58786f2a8467c601f281c67034fd4
\ No newline at end of file
+0e1d84f2f456e7680bb667266745b629ddf3605f
\ No newline at end of file
** May you share freely, never taking more than you give.
**
*************************************************************************
-** $Id: btree.c,v 1.442 2008/03/23 00:20:36 drh Exp $
+** $Id: btree.c,v 1.443 2008/03/25 00:22:21 drh Exp $
**
** This file implements a external (disk-based) database using BTrees.
** See the header comment on "btreeInt.h" for additional information.
return rc;
}
-/*
-** Default key comparison function to be used if no comparison function
-** is specified on the sqlite3BtreeCursor() call.
-*/
-static int dfltCompare(
- void *NotUsed, /* User data is not used */
- int n1, const void *p1, /* First key to compare */
- int n2, const void *p2 /* Second key to compare */
-){
- int c;
- c = memcmp(p1, p2, n1<n2 ? n1 : n2);
- if( c==0 ){
- c = n1 - n2;
- }
- return c;
-}
-
/*
** Create a new cursor for the BTree whose root is on the page
** iTable. The act of acquiring a cursor gets a read lock on
** No checking is done to make sure that page iTable really is the
** root page of a b-tree. If it is not, then the cursor acquired
** will not work correctly.
-**
-** The comparison function must be logically the same for every cursor
-** on a particular table. Changing the comparison function will result
-** in incorrect operations. If the comparison function is NULL, a
-** default comparison function is used. The comparison function is
-** always ignored for INTKEY tables.
*/
static int btreeCursor(
- Btree *p, /* The btree */
- int iTable, /* Root page of table to open */
- int wrFlag, /* 1 to write. 0 read-only */
- int (*xCmp)(void*,int,const void*,int,const void*), /* Key Comparison func */
- void *pArg, /* First arg to xCompare() */
- BtCursor **ppCur /* Write new cursor here */
+ Btree *p, /* The btree */
+ int iTable, /* Root page of table to open */
+ int wrFlag, /* 1 to write. 0 read-only */
+ struct KeyInfo *pKeyInfo, /* First arg to comparison function */
+ BtCursor **ppCur /* Write new cursor here */
){
int rc;
BtCursor *pCur;
** variables, link the cursor into the BtShared list and set *ppCur (the
** output argument to this function).
*/
- pCur->xCompare = xCmp ? xCmp : dfltCompare;
- pCur->pArg = pArg;
+ pCur->pKeyInfo = pKeyInfo;
pCur->pBtree = p;
pCur->pBt = pBt;
pCur->wrFlag = wrFlag;
return rc;
}
int sqlite3BtreeCursor(
- Btree *p, /* The btree */
- int iTable, /* Root page of table to open */
- int wrFlag, /* 1 to write. 0 read-only */
- int (*xCmp)(void*,int,const void*,int,const void*), /* Key Comparison func */
- void *pArg, /* First arg to xCompare() */
- BtCursor **ppCur /* Write new cursor here */
+ Btree *p, /* The btree */
+ int iTable, /* Root page of table to open */
+ int wrFlag, /* 1 to write. 0 read-only */
+ struct KeyInfo *pKeyInfo, /* First arg to xCompare() */
+ BtCursor **ppCur /* Write new cursor here */
){
int rc;
sqlite3BtreeEnter(p);
p->pBt->db = p->db;
- rc = btreeCursor(p, iTable, wrFlag, xCmp, pArg, ppCur);
+ rc = btreeCursor(p, iTable, wrFlag, pKeyInfo, ppCur);
sqlite3BtreeLeave(p);
return rc;
}
**
** For INTKEY tables, only the nKey parameter is used. pKey is
** ignored. For other tables, nKey is the number of bytes of data
-** in pKey. The comparison function specified when the cursor was
-** created is used to compare keys.
+** in pKey.
**
** If an exact match is not found, then the cursor is always
** left pointing at a leaf page which would hold the entry if it
int *pRes /* Search result flag */
){
int rc;
+ VdbeParsedRecord *pPKey;
+ char aSpace[200];
assert( cursorHoldsMutex(pCur) );
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
assert( pCur->pPage->nCell==0 );
return SQLITE_OK;
}
+ if( pCur->pPage->intKey ){
+ pPKey = 0;
+ }else{
+ pPKey = sqlite3VdbeRecordParse(pCur->pKeyInfo, nKey, pKey,
+ aSpace, sizeof(aSpace));
+ if( pPKey==0 ) return SQLITE_NOMEM;
+ }
for(;;){
int lwr, upr;
Pgno chldPg;
lwr = 0;
upr = pPage->nCell-1;
if( !pPage->intKey && pKey==0 ){
- return SQLITE_CORRUPT_BKPT;
+ rc = SQLITE_CORRUPT_BKPT;
+ goto moveto_finish;
}
if( biasRight ){
pCur->idx = upr;
pCellKey = (void *)fetchPayload(pCur, &available, 0);
nCellKey = pCur->info.nKey;
if( available>=nCellKey ){
- c = pCur->xCompare(pCur->pArg, nCellKey, pCellKey, nKey, pKey);
+ c = sqlite3VdbeRecordCompareParsed(nCellKey, pCellKey, pPKey);
}else{
pCellKey = sqlite3_malloc( nCellKey );
if( pCellKey==0 ) return SQLITE_NOMEM;
rc = sqlite3BtreeKey(pCur, 0, nCellKey, (void *)pCellKey);
- c = pCur->xCompare(pCur->pArg, nCellKey, pCellKey, nKey, pKey);
+ c = sqlite3VdbeRecordCompareParsed(nCellKey, pCellKey, pPKey);
sqlite3_free(pCellKey);
- if( rc ){
- return rc;
- }
+ if( rc ) goto moveto_finish;
}
}
if( c==0 ){
break;
}else{
if( pRes ) *pRes = 0;
- return SQLITE_OK;
+ rc = SQLITE_OK;
+ goto moveto_finish;
}
}
if( c<0 ){
if( chldPg==0 ){
assert( pCur->idx>=0 && pCur->idx<pCur->pPage->nCell );
if( pRes ) *pRes = c;
- return SQLITE_OK;
+ rc = SQLITE_OK;
+ goto moveto_finish;
}
pCur->idx = lwr;
pCur->info.nSize = 0;
rc = moveToChild(pCur, chldPg);
- if( rc ){
- return rc;
- }
+ if( rc ) goto moveto_finish;
}
- /* NOT REACHED */
+moveto_finish:
+ sqlite3VdbeRecordUnparse(pPKey);
+ return rc;
}
** subsystem. See comments in the source code for a detailed description
** of what each interface routine does.
**
-** @(#) $Id: btree.h,v 1.94 2007/12/07 18:55:28 drh Exp $
+** @(#) $Id: btree.h,v 1.95 2008/03/25 00:22:21 drh Exp $
*/
#ifndef _BTREE_H_
#define _BTREE_H_
void sqlite3BtreeTripAllCursors(Btree*, int);
int sqlite3BtreeCursor(
- Btree*, /* BTree containing table to open */
- int iTable, /* Index of root page */
- int wrFlag, /* 1 for writing. 0 for read-only */
- int(*)(void*,int,const void*,int,const void*), /* Key comparison function */
- void*, /* First argument to compare function */
- BtCursor **ppCursor /* Returned cursor */
+ Btree*, /* BTree containing table to open */
+ int iTable, /* Index of root page */
+ int wrFlag, /* 1 for writing. 0 for read-only */
+ struct KeyInfo*, /* First argument to compare function */
+ BtCursor **ppCursor /* Returned cursor */
);
int sqlite3BtreeCloseCursor(BtCursor*);
** May you share freely, never taking more than you give.
**
*************************************************************************
-** $Id: btreeInt.h,v 1.17 2008/03/04 17:45:01 mlcreech Exp $
+** $Id: btreeInt.h,v 1.18 2008/03/25 00:22:21 drh Exp $
**
** This file implements a external (disk-based) database using BTrees.
** For a detailed discussion of BTrees, refer to
Btree *pBtree; /* The Btree to which this cursor belongs */
BtShared *pBt; /* The BtShared this cursor points to */
BtCursor *pNext, *pPrev; /* Forms a linked list of all cursors */
- int (*xCompare)(void*,int,const void*,int,const void*); /* Key comp func */
- void *pArg; /* First arg to xCompare() */
+ struct KeyInfo *pKeyInfo; /* Argument passed to comparison function */
Pgno pgnoRoot; /* The root page of this tree */
MemPage *pPage; /* Page that contains the entry */
int idx; /* Index of the entry in pPage->aCell[] */
** interface, and routines that contribute to loading the database schema
** from disk.
**
-** $Id: prepare.c,v 1.80 2008/03/20 14:03:29 drh Exp $
+** $Id: prepare.c,v 1.81 2008/03/25 00:22:21 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
return SQLITE_OK;
}
sqlite3BtreeEnter(pDb->pBt);
- rc = sqlite3BtreeCursor(pDb->pBt, MASTER_ROOT, 0, 0, 0, &curMain);
+ rc = sqlite3BtreeCursor(pDb->pBt, MASTER_ROOT, 0, 0, &curMain);
if( rc!=SQLITE_OK && rc!=SQLITE_EMPTY ){
sqlite3SetString(pzErrMsg, sqlite3ErrStr(rc), (char*)0);
sqlite3BtreeLeave(pDb->pBt);
Btree *pBt;
pBt = db->aDb[iDb].pBt;
if( pBt==0 ) continue;
- rc = sqlite3BtreeCursor(pBt, MASTER_ROOT, 0, 0, 0, &curTemp);
+ rc = sqlite3BtreeCursor(pBt, MASTER_ROOT, 0, 0, &curTemp);
if( rc==SQLITE_OK ){
rc = sqlite3BtreeGetMeta(pBt, 1, (u32 *)&cookie);
if( rc==SQLITE_OK && cookie!=db->aDb[iDb].pSchema->schema_cookie ){
** is not included in the SQLite library. It is used for automated
** testing of the SQLite library.
**
-** $Id: test3.c,v 1.91 2008/03/04 17:45:02 mlcreech Exp $
+** $Id: test3.c,v 1.92 2008/03/25 00:22:21 drh Exp $
*/
#include "sqliteInt.h"
#include "btreeInt.h"
if( Tcl_GetInt(interp, argv[2], &iTable) ) return TCL_ERROR;
if( Tcl_GetBoolean(interp, argv[3], &wrFlag) ) return TCL_ERROR;
sqlite3BtreeEnter(pBt);
- rc = sqlite3BtreeCursor(pBt, iTable, wrFlag, 0, 0, &pCur);
+ rc = sqlite3BtreeCursor(pBt, iTable, wrFlag, 0, &pCur);
sqlite3BtreeLeave(pBt);
if( rc ){
Tcl_AppendResult(interp, errorName(rc), 0);
** in this file for details. If in doubt, do not deviate from existing
** commenting and indentation practices when changing or adding code.
**
-** $Id: vdbe.c,v 1.715 2008/03/21 17:13:13 drh Exp $
+** $Id: vdbe.c,v 1.716 2008/03/25 00:22:21 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
** Convert P2 registers beginning with P1 into a single entry
** suitable for use as a data record in a database table or as a key
** in an index. The details of the format are irrelavant as long as
-** the OP_Column opcode can decode the record later and as long as the
-** sqlite3VdbeRecordCompare function will correctly compare two encoded
-** records. Refer to source code comments for the details of the record
+** the OP_Column opcode can decode the record later.
+** Refer to source code comments for the details of the record
** format.
**
** P4 may be a string that is P1 characters long. The nth character of the
pCur = allocateCursor(p, i, iDb);
if( pCur==0 ) goto no_mem;
pCur->nullRow = 1;
- /* We always provide a key comparison function. If the table being
- ** opened is of type INTKEY, the comparision function will be ignored. */
- rc = sqlite3BtreeCursor(pX, p2, wrFlag,
- sqlite3VdbeRecordCompare, pOp->p4.p,
- &pCur->pCursor);
+ rc = sqlite3BtreeCursor(pX, p2, wrFlag, pOp->p4.p, &pCur->pCursor);
if( pOp->p4type==P4_KEYINFO ){
pCur->pKeyInfo = pOp->p4.pKeyInfo;
pCur->pIncrKey = &pCur->pKeyInfo->incrKey;
rc = sqlite3BtreeCreateTable(pCx->pBt, &pgno, BTREE_ZERODATA);
if( rc==SQLITE_OK ){
assert( pgno==MASTER_ROOT+1 );
- rc = sqlite3BtreeCursor(pCx->pBt, pgno, 1, sqlite3VdbeRecordCompare,
- pOp->p4.z, &pCx->pCursor);
+ rc = sqlite3BtreeCursor(pCx->pBt, pgno, 1,
+ (KeyInfo*)pOp->p4.z, &pCx->pCursor);
pCx->pKeyInfo = pOp->p4.pKeyInfo;
pCx->pKeyInfo->enc = ENC(p->db);
pCx->pIncrKey = &pCx->pKeyInfo->incrKey;
}
pCx->isTable = 0;
}else{
- rc = sqlite3BtreeCursor(pCx->pBt, MASTER_ROOT, 1, 0, 0, &pCx->pCursor);
+ rc = sqlite3BtreeCursor(pCx->pBt, MASTER_ROOT, 1, 0, &pCx->pCursor);
pCx->isTable = 1;
pCx->pIncrKey = &pCx->bogusIncrKey;
}
** or VDBE. The VDBE implements an abstract machine that runs a
** simple program to access and modify the underlying database.
**
-** $Id: vdbe.h,v 1.126 2008/03/22 01:07:18 drh Exp $
+** $Id: vdbe.h,v 1.127 2008/03/25 00:22:21 drh Exp $
*/
#ifndef _SQLITE_VDBE_H_
#define _SQLITE_VDBE_H_
*/
typedef struct VdbeFunc VdbeFunc;
typedef struct Mem Mem;
+typedef struct VdbeParsedRecord VdbeParsedRecord;
/*
** A single instruction of the virtual machine has an opcode
void sqlite3VdbeSetSql(Vdbe*, const char *z, int n);
void sqlite3VdbeSwap(Vdbe*,Vdbe*);
+VdbeParsedRecord *sqlite3VdbeRecordParse(KeyInfo*,int,const void*,void*,int);
+void sqlite3VdbeRecordUnparse(VdbeParsedRecord*);
+int sqlite3VdbeRecordCompareParsed(int,const void*,VdbeParsedRecord*);
+
+
#ifndef NDEBUG
void sqlite3VdbeComment(Vdbe*, const char*, ...);
# define VdbeComment(X) sqlite3VdbeComment X
int sqlite3VdbeIdxKeyCompare(Cursor*,int,const unsigned char*,int*);
int sqlite3VdbeIdxRowid(BtCursor *, i64 *);
int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*);
-int sqlite3VdbeRecordCompare(void*,int,const void*,int, const void*);
int sqlite3VdbeIdxRowidLen(const u8*);
int sqlite3VdbeExec(Vdbe*);
int sqlite3VdbeList(Vdbe*);
*/
#define GetVarint(A,B) ((B = *(A))<=0x7f ? 1 : sqlite3GetVarint32(A, &B))
+#if 0
/*
** This function compares the two table rows or index records specified by
** {nKey1, pKey1} and {nKey2, pKey2}, returning a negative, zero
return rc;
}
+#endif
+
+/*
+** An instance of the following structure holds information about a
+** single index record that has already been parsed out into individual
+** values.
+**
+** A record is an object that contains one or more fields of data.
+** Records are used to store the content of a table row and to store
+** the key of an index. A blob encoding of a record is created by
+** the OP_MakeRecord opcode of the VDBE and is disassemblied by the
+** OP_Column opcode.
+**
+** This structure holds a record that has already been disassembled
+** into its constitutent fields.
+*/
+struct VdbeParsedRecord {
+ KeyInfo *pKeyInfo; /* Collation and sort-order information */
+ u16 nField; /* Number of entries in apMem[] */
+ u8 needFree; /* True if memory obtained from sqlite3_malloc() */
+ u8 needDestroy; /* True if apMem[]s should be destroyed on close */
+ Mem *apMem[1]; /* Values */
+};
+
+/*
+** Given the nKey-byte encoding of a record in pKey[], parse the
+** record into a VdbeParsedRecord structure. Return a pointer to
+** that structure.
+**
+** The calling function might provide szSpace bytes of memory
+** space at pSpace. This space can be used to hold the returned
+** VDbeParsedRecord structure if it is large enough. If it is
+** not big enough, space is obtained from sqlite3_malloc().
+**
+** The returned structure should be closed by a call to
+** sqlite3VdbeRecordUnparse().
+*/
+VdbeParsedRecord *sqlite3VdbeRecordParse(
+ KeyInfo *pKeyInfo, /* Information about the record format */
+ int nKey, /* Size of the binary record */
+ const void *pKey, /* The binary record */
+ void *pSpace, /* Space available to hold resulting object */
+ int szSpace /* Size of pSpace[] in bytes */
+){
+ const unsigned char *aKey = (const unsigned char *)pKey;
+ VdbeParsedRecord *p;
+ int nByte;
+ int i, idx, d;
+ u32 szHdr;
+ Mem *pMem;
+
+ nByte = sizeof(*p) + sizeof(Mem*)*pKeyInfo->nField
+ + sizeof(Mem)*(pKeyInfo->nField+1);
+ if( nByte>szSpace ){
+ p = sqlite3DbMallocRaw(pKeyInfo->db, nByte);
+ if( p==0 ) return 0;
+ p->needFree = 1;
+ }else{
+ p = pSpace;
+ p->needFree = 0;
+ }
+ p->pKeyInfo = pKeyInfo;
+ p->nField = pKeyInfo->nField + 1;
+ p->needDestroy = 1;
+ pMem = (Mem*)&p->apMem[pKeyInfo->nField+1];
+ idx = GetVarint(aKey, szHdr);
+ d = szHdr;
+ i = 0;
+ while( idx<szHdr && i<p->nField ){
+ u32 serial_type;
+
+ idx += GetVarint( aKey+idx, serial_type);
+ if( d>=nKey && sqlite3VdbeSerialTypeLen(serial_type)>0 ) break;
+ pMem->enc = pKeyInfo->enc;
+ pMem->db = pKeyInfo->db;
+ pMem->flags = 0;
+ d += sqlite3VdbeSerialGet(&aKey[d], serial_type, pMem);
+ p->apMem[i++] = pMem++;
+ }
+ p->nField = i;
+ return (void*)p;
+}
+
+/*
+** This routine destroys a VdbeParsedRecord object
+*/
+void sqlite3VdbeRecordUnparse(VdbeParsedRecord *p){
+ if( p ){
+ if( p->needDestroy ){
+ int i;
+ for(i=0; i<p->nField; i++){
+ if( p->apMem[i]->flags & MEM_Dyn ){
+ sqlite3VdbeMemRelease(p->apMem[i]);
+ }
+ }
+ }
+ if( p->needFree ){
+ sqlite3_free(p);
+ }
+ }
+}
+
+/*
+** This function compares the two table rows or index records
+** specified by {nKey1, pKey1} and pPKey2. It returns a negative, zero
+** or positive integer if {nKey1, pKey1} is less than, equal to or
+** greater than pPKey2. The {nKey1, pKey1} key must be a blob
+** created by th OP_MakeRecord opcode of the VDBE. The pPKey2
+** key must be a parsed key such as obtained from
+** sqlite3VdbeParseRecord.
+**
+** Key1 and Key2 do not have to contain the same number of fields.
+** But if the lengths differ, Key2 must be the shorter of the two.
+**
+** Historical note: In earlier versions of this routine both Key1
+** and Key2 were blobs obtained from OP_MakeRecord. But we found
+** that in typical use the same Key2 would be submitted multiple times
+** in a row. So an optimization was added to parse the Key2 key
+** separately and submit the parsed version. In this way, we avoid
+** parsing the same Key2 multiple times in a row.
+*/
+int sqlite3VdbeRecordCompareParsed(
+ int nKey1, const void *pKey1,
+ VdbeParsedRecord *pPKey2
+){
+ u32 d1; /* Offset into aKey[] of next data element */
+ u32 idx1; /* Offset into aKey[] of next header element */
+ u32 szHdr1; /* Number of bytes in header */
+ int i = 0;
+ int nField;
+ int rc = 0;
+ const unsigned char *aKey1 = (const unsigned char *)pKey1;
+ KeyInfo *pKeyInfo;
+ Mem mem1;
+
+ pKeyInfo = pPKey2->pKeyInfo;
+ mem1.enc = pKeyInfo->enc;
+ mem1.db = pKeyInfo->db;
+ mem1.flags = 0;
+
+ idx1 = GetVarint(aKey1, szHdr1);
+ d1 = szHdr1;
+ nField = pKeyInfo->nField;
+ while( idx1<szHdr1 && i<pPKey2->nField ){
+ u32 serial_type1;
+
+ /* Read the serial types for the next element in each key. */
+ idx1 += GetVarint( aKey1+idx1, serial_type1 );
+ if( d1>=nKey1 && sqlite3VdbeSerialTypeLen(serial_type1)>0 ) break;
+
+ /* Extract the values to be compared.
+ */
+ d1 += sqlite3VdbeSerialGet(&aKey1[d1], serial_type1, &mem1);
+
+ /* Do the comparison
+ */
+ rc = sqlite3MemCompare(&mem1, pPKey2->apMem[i],
+ i<nField ? pKeyInfo->aColl[i] : 0);
+ if( mem1.flags&MEM_Dyn ) sqlite3VdbeMemRelease(&mem1);
+ if( rc!=0 ){
+ break;
+ }
+ i++;
+ }
+
+ /* One of the keys ran out of fields, but all the fields up to that point
+ ** were equal. If the incrKey flag is true, then the second key is
+ ** treated as larger.
+ */
+ if( rc==0 ){
+ if( pKeyInfo->incrKey ){
+ rc = -1;
+ }else if( !pKeyInfo->prefixIsEqual ){
+ if( d1<nKey1 ){
+ rc = 1;
+ }
+ }
+ }else if( pKeyInfo->aSortOrder && i<pKeyInfo->nField
+ && pKeyInfo->aSortOrder[i] ){
+ rc = -rc;
+ }
+
+ return rc;
+}
/*
** The argument is an index entry composed using the OP_MakeRecord opcode.
BtCursor *pCur = pC->pCursor;
int lenRowid;
Mem m;
+ VdbeParsedRecord *pRec;
+ char zSpace[200];
sqlite3BtreeKeySize(pCur, &nCellKey);
if( nCellKey<=0 ){
return rc;
}
lenRowid = sqlite3VdbeIdxRowidLen((u8*)m.z);
- *res = sqlite3VdbeRecordCompare(pC->pKeyInfo, m.n-lenRowid, m.z, nKey, pKey);
+ pRec = sqlite3VdbeRecordParse(pC->pKeyInfo, nKey, pKey,
+ zSpace, sizeof(zSpace));
+ if( pRec==0 ){
+ return SQLITE_NOMEM;
+ }
+ *res = sqlite3VdbeRecordCompareParsed(m.n-lenRowid, m.z, pRec);
+ sqlite3VdbeRecordUnparse(pRec);
sqlite3VdbeMemRelease(&m);
return SQLITE_OK;
}
+++ /dev/null
-# 2001 September 15
-#
-# The author disclaims copyright to this source code. In place of
-# a legal notice, here is a blessing:
-#
-# May you do good and not evil.
-# May you find forgiveness for yourself and forgive others.
-# May you share freely, never taking more than you give.
-#
-#***********************************************************************
-# This file implements regression tests for SQLite library. The
-# focus of this script is btree database backend
-#
-# $Id: btree.test,v 1.43 2008/02/02 20:47:38 drh Exp $
-
-
-set testdir [file dirname $argv0]
-source $testdir/tester.tcl
-
-ifcapable default_autovacuum {
- finish_test
- return
-}
-
-# 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 2000 0} ::b1]
-} {0}
-
-# The second element of the list returned by btree_pager_stats is the
-# number of pages currently checked out. We'll be checking this value
-# frequently during this test script, to make sure the btree library
-# is properly releasing the pages it checks out, and thus avoiding
-# page leaks.
-#
-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 2000 0} ::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.4.1 {
- lindex [btree_pager_stats $::b1] 1
-} {1}
-do_test btree-1.5 {
- 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 100 1.00} msg]
- lappend rc $msg
-} {0 {}}
-do_test btree-1.7 {
- btree_move_to $::c1 100
- btree_key $::c1
-} {100}
-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
-} {1024}
-do_test btree-1.12 {
- lindex [btree_pager_stats $::b1] 1
-} {0}
-
-# Reopen the database and attempt to read the record that we wrote.
-#
-do_test btree-2.1 {
- set rc [catch {btree_cursor $::b1 1 1} ::c1]
- if {$rc} {lappend rc $::c1}
- set rc
-} {0}
-do_test btree-2.1.1 {
- btree_cursor_list $::b1
-} {}
-do_test btree-2.2 {
- btree_move_to $::c1 99
-} {1}
-do_test btree-2.3 {
- btree_move_to $::c1 101
-} {-1}
-do_test btree-2.4 {
- btree_move_to $::c1 100
-} {0}
-do_test btree-2.5 {
- btree_key $::c1
-} {100}
-do_test btree-2.6 {
- btree_data $::c1
-} {1.00}
-do_test btree-2.7 {
- lindex [btree_pager_stats $::b1] 1
-} {1}
-
-# Do some additional inserts
-#
-do_test btree-3.1 {
- btree_begin_transaction $::b1
- btree_insert $::c1 200 2.00
- btree_move_to $::c1 200
- btree_key $::c1
-} {200}
-do_test btree-3.1.1 {
- lindex [btree_pager_stats $::b1] 1
-} {1}
-do_test btree-3.2 {
- btree_insert $::c1 300 3.00
- btree_move_to $::c1 300
- btree_key $::c1
-} {300}
-do_test btree-3.4 {
- btree_insert $::c1 400 4.00
- btree_move_to $::c1 400
- btree_key $::c1
-} {400}
-do_test btree-3.5 {
- btree_insert $::c1 500 5.00
- btree_move_to $::c1 500
- btree_key $::c1
-} {500}
-do_test btree-3.6 {
- btree_insert $::c1 600 6.00
- btree_move_to $::c1 600
- btree_key $::c1
-} {600}
-#btree_page_dump $::b1 2
-do_test btree-3.7 {
- set rc [btree_move_to $::c1 0]
- expr {$rc>0}
-} {1}
-do_test btree-3.8 {
- btree_key $::c1
-} {100}
-do_test btree-3.9 {
- btree_data $::c1
-} {1.00}
-do_test btree-3.10 {
- btree_next $::c1
- btree_key $::c1
-} {200}
-do_test btree-3.11 {
- btree_data $::c1
-} {2.00}
-do_test btree-3.12 {
- btree_next $::c1
- btree_key $::c1
-} {300}
-do_test btree-3.13 {
- btree_data $::c1
-} {3.00}
-do_test btree-3.14 {
- btree_next $::c1
- btree_key $::c1
-} {400}
-do_test btree-3.15 {
- btree_data $::c1
-} {4.00}
-do_test btree-3.16 {
- btree_next $::c1
- btree_key $::c1
-} {500}
-do_test btree-3.17 {
- btree_data $::c1
-} {5.00}
-do_test btree-3.18 {
- btree_next $::c1
- btree_key $::c1
-} {600}
-do_test btree-3.19 {
- btree_data $::c1
-} {6.00}
-do_test btree-3.20.1 {
- btree_next $::c1
- btree_key $::c1
-} {0}
-do_test btree-3.20.2 {
- btree_eof $::c1
-} {1}
-# This test case used to test that one couldn't request data from an
-# invalid cursor. That is now an assert()ed condition.
-#
-# do_test btree-3.21 {
-# set rc [catch {btree_data $::c1} res]
-# lappend rc $res
-# } {1 SQLITE_INTERNAL}
-
-# 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.22.1 {
- lindex [btree_pager_stats $::b1] 1
-} {1}
-do_test btree-3.23 {
- set rc [catch {btree_commit $::b1} msg]
- lappend rc $msg
-} {0 {}}
-do_test btree-3.23.1 {
- lindex [btree_pager_stats $::b1] 1
-} {0}
-do_test btree-3.24 {
- file size test1.bt
-} {1024}
-do_test btree-3.25 {
- 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
-} {1}
-do_test btree-3.26 {
- set rc [btree_move_to $::c1 0]
- expr {$rc>0}
-} {1}
-do_test btree-3.27 {
- btree_key $::c1
-} {100}
-do_test btree-3.28 {
- btree_data $::c1
-} {1.00}
-do_test btree-3.29 {
- btree_next $::c1
- btree_key $::c1
-} {200}
-do_test btree-3.30 {
- btree_data $::c1
-} {2.00}
-do_test btree-3.31 {
- btree_next $::c1
- btree_key $::c1
-} {300}
-do_test btree-3.32 {
- btree_data $::c1
-} {3.00}
-do_test btree-3.33 {
- btree_next $::c1
- btree_key $::c1
-} {400}
-do_test btree-3.34 {
- btree_data $::c1
-} {4.00}
-do_test btree-3.35 {
- btree_next $::c1
- btree_key $::c1
-} {500}
-do_test btree-3.36 {
- btree_data $::c1
-} {5.00}
-do_test btree-3.37 {
- btree_next $::c1
- btree_key $::c1
-} {600}
-do_test btree-3.38 {
- btree_data $::c1
-} {6.00}
-do_test btree-3.39 {
- btree_next $::c1
- btree_key $::c1
-} {0}
-# This test case used to test that requesting data from an invalid cursor
-# returned SQLITE_INTERNAL. That is now an assert()ed condition.
-#
-# do_test btree-3.40 {
-# set rc [catch {btree_data $::c1} res]
-# lappend rc $res
-# } {1 SQLITE_INTERNAL}
-do_test btree-3.41 {
- lindex [btree_pager_stats $::b1] 1
-} {1}
-
-
-# Now try a delete
-#
-do_test btree-4.1 {
- btree_begin_transaction $::b1
- btree_move_to $::c1 100
- btree_key $::c1
-} {100}
-do_test btree-4.1.1 {
- lindex [btree_pager_stats $::b1] 1
-} {1}
-do_test btree-4.2 {
- btree_delete $::c1
-} {}
-do_test btree-4.3 {
- btree_move_to $::c1 100
- btree_key $::c1
-} {200}
-do_test btree-4.4 {
- btree_next $::c1
- btree_key $::c1
-} {300}
-do_test btree-4.5 {
- btree_next $::c1
- btree_key $::c1
-} {400}
-do_test btree-4.4 {
- btree_move_to $::c1 0
- set r {}
- while 1 {
- set key [btree_key $::c1]
- if {[btree_eof $::c1]} break
- lappend r $key
- lappend r [btree_data $::c1]
- btree_next $::c1
- }
- set r
-} {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 0
- set r {}
- while 1 {
- set key [btree_key $::c1]
- if {[btree_eof $::c1]} break
- lappend r $key
- lappend r [btree_data $::c1]
- btree_next $::c1
- }
- set r
-} {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
-} {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 2000 0]
- set ::c1 [btree_cursor $::b1 1 1]
- lindex [btree_pager_stats $::b1] 1
-} {1}
-do_test btree-4.9 {
- set r {}
- btree_first $::c1
- while 1 {
- set key [btree_key $::c1]
- if {[btree_eof $::c1]} break
- lappend r $key
- lappend r [btree_data $::c1]
- btree_next $::c1
- }
- set r
-} {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}
-do_test btree-5.2 {
- set rc [catch {
- btree_update_meta $::b1 0 1 2 3 4 5 6 7 8 9
- } msg]
- lappend rc $msg
-} {1 SQLITE_ERROR}
-do_test btree-5.3 {
- btree_begin_transaction $::b1
- set rc [catch {
- btree_update_meta $::b1 0 1 2 3 0 5 6 0 8 9
- } msg]
- lappend rc $msg
-} {0 {}}
-do_test btree-5.4 {
- btree_get_meta $::b1
-} {0 1 2 3 0 5 6 0 8 9}
-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}
-do_test btree-5.6 {
- btree_begin_transaction $::b1
- btree_update_meta $::b1 0 10 20 30 0 50 60 0 80 90
- btree_commit $::b1
- btree_get_meta $::b1
-} {0 10 20 30 0 50 60 0 80 90}
-
-proc select_all {cursor} {
- set r {}
- btree_first $cursor
- while {![btree_eof $cursor]} {
- set key [btree_key $cursor]
- lappend r $key
- lappend r [btree_data $cursor]
- btree_next $cursor
- }
- return $r
-}
-proc select_keys {cursor} {
- set r {}
- btree_first $cursor
- while {![btree_eof $cursor]} {
- set key [btree_key $cursor]
- lappend r $key
- btree_next $cursor
- }
- return $r
-}
-
-# Try to create a new table in the database file
-#
-do_test btree-6.1 {
- 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 0]
-} {2}
-do_test btree-6.2.1 {
- lindex [btree_pager_stats $::b1] 1
-} {1}
-do_test btree-6.2.2 {
- set ::c2 [btree_cursor $::b1 $::t2 1]
- lindex [btree_pager_stats $::b1] 1
-} {2}
-do_test btree-6.2.3 {
- btree_insert $::c2 ten 10
- btree_move_to $::c2 ten
- btree_key $::c2
-} {ten}
-do_test btree-6.3 {
- btree_commit $::b1
- set ::c1 [btree_cursor $::b1 1 1]
- lindex [btree_pager_stats $::b1] 1
-} {2}
-do_test btree-6.3.1 {
- select_all $::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
-} {ten 10}
-
-# Drop the new table, then create it again anew.
-#
-do_test btree-6.5 {
- btree_begin_transaction $::b1
-} {}
-do_test btree-6.6 {
- btree_close_cursor $::c2
-} {}
-do_test btree-6.6.1 {
- lindex [btree_pager_stats $::b1] 1
-} {1}
-do_test btree-6.7 {
- btree_close_cursor $::c1
- btree_drop_table $::b1 $::t2
-} {}
-do_test btree-6.7.1 {
- lindex [btree_get_meta $::b1] 0
-} {1}
-do_test btree-6.8 {
- 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
-} {2}
-
-# This test case used to test that requesting the key from an invalid cursor
-# returned an empty string. But that is now an assert()ed condition.
-#
-# do_test btree-6.9.1 {
-# btree_move_to $::c2 {}
-# btree_key $::c2
-# } {}
-
-# If we drop table 1 it just clears the table. Table 1 always exists.
-#
-do_test btree-6.10 {
- btree_close_cursor $::c2
- btree_drop_table $::b1 1
- set ::c2 [btree_cursor $::b1 $::t2 1]
- set ::c1 [btree_cursor $::b1 1 1]
- btree_first $::c1
- btree_eof $::c1
-} {1}
-do_test btree-6.11 {
- btree_commit $::b1
- select_all $::c1
-} {}
-do_test btree-6.12 {
- select_all $::c2
-} {}
-do_test btree-6.13 {
- btree_close_cursor $::c2
- lindex [btree_pager_stats $::b1] 1
-} {1}
-
-# Check to see that pages defragment properly. To do this test we will
-#
-# 1. Fill the first page of table 1 with data.
-# 2. Delete every other entry of table 1.
-# 3. Insert a single entry that requires more contiguous
-# space than is available.
-#
-do_test btree-7.1 {
- btree_begin_transaction $::b1
-} {}
-catch {unset key}
-catch {unset data}
-
-# Check to see that data on overflow pages work correctly.
-#
-do_test btree-8.1 {
- set data "*** This is a very long key "
- while {[string length $data]<1234} {append data $data}
- set ::data $data
- btree_insert $::c1 2020 $data
-} {}
-btree_page_dump $::b1 1
-btree_page_dump $::b1 2
-do_test btree-8.1.1 {
- lindex [btree_pager_stats $::b1] 1
-} {1}
-btree_pager_ref_dump $::b1
-do_test btree-8.2 {
- btree_move_to $::c1 2020
- string length [btree_data $::c1]
-} [string length $::data]
-do_test btree-8.3 {
- btree_data $::c1
-} $::data
-do_test btree-8.4 {
- btree_delete $::c1
-} {}
-do_test btree-8.4.1 {
- lindex [btree_get_meta $::b1] 0
-} [expr {int(([string length $::data]-238+1019)/1020)}]
-do_test btree-8.4.2 {
- btree_integrity_check $::b1 1 2
-} {}
-do_test btree-8.5 {
- set data "*** This is an even longer key "
- while {[string length $data]<2000} {append data $data}
- append data END
- set ::data $data
- btree_insert $::c1 2030 $data
-} {}
-do_test btree-8.6 {
- btree_move_to $::c1 2030
- string length [btree_data $::c1]
-} [string length $::data]
-do_test btree-8.7 {
- btree_data $::c1
-} $::data
-do_test btree-8.8 {
- btree_commit $::b1
- btree_data $::c1
-} $::data
-do_test btree-8.9.1 {
- btree_close_cursor $::c1
- btree_close $::b1
- set ::b1 [btree_open test1.bt 2000 0]
- set ::c1 [btree_cursor $::b1 1 1]
- btree_move_to $::c1 2030
- btree_data $::c1
-} $::data
-do_test btree-8.9.2 {
- btree_integrity_check $::b1 1 2
-} {}
-do_test btree-8.10 {
- btree_begin_transaction $::b1
- btree_delete $::c1
-} {}
-do_test btree-8.11 {
- lindex [btree_get_meta $::b1] 0
-} {4}
-
-# Now check out keys on overflow pages.
-#
-do_test btree-8.12.1 {
- set ::keyprefix "This is a long prefix to a key "
- while {[string length $::keyprefix]<256} {append ::keyprefix $::keyprefix}
- btree_close_cursor $::c1
- btree_clear_table $::b1 2
- lindex [btree_get_meta $::b1] 0
-} {4}
-do_test btree-8.12.2 {
- btree_integrity_check $::b1 1 2
-} {}
-do_test btree-8.12.3 {
- set ::c1 [btree_cursor $::b1 2 1]
- btree_insert $::c1 ${::keyprefix}1 1
- btree_first $::c1
- btree_data $::c1
-} {1}
-do_test btree-8.13 {
- btree_key $::c1
-} ${keyprefix}1
-do_test btree-8.14 {
- btree_insert $::c1 ${::keyprefix}2 2
- btree_insert $::c1 ${::keyprefix}3 3
- btree_last $::c1
- btree_key $::c1
-} ${keyprefix}3
-do_test btree-8.15 {
- btree_move_to $::c1 ${::keyprefix}2
- btree_data $::c1
-} {2}
-do_test btree-8.16 {
- btree_move_to $::c1 ${::keyprefix}1
- btree_data $::c1
-} {1}
-do_test btree-8.17 {
- btree_move_to $::c1 ${::keyprefix}3
- btree_data $::c1
-} {3}
-do_test btree-8.18 {
- lindex [btree_get_meta $::b1] 0
-} {1}
-do_test btree-8.19 {
- btree_move_to $::c1 ${::keyprefix}2
- btree_key $::c1
-} ${::keyprefix}2
-#btree_page_dump $::b1 2
-do_test btree-8.20 {
- btree_delete $::c1
- btree_next $::c1
- btree_key $::c1
-} ${::keyprefix}3
-#btree_page_dump $::b1 2
-do_test btree-8.21 {
- lindex [btree_get_meta $::b1] 0
-} {2}
-do_test btree-8.22 {
- lindex [btree_pager_stats $::b1] 1
-} {2}
-do_test btree-8.23.1 {
- btree_close_cursor $::c1
- btree_drop_table $::b1 2
- btree_integrity_check $::b1 1
-} {}
-do_test btree-8.23.2 {
- btree_create_table $::b1 0
-} {2}
-do_test btree-8.23.3 {
- set ::c1 [btree_cursor $::b1 2 1]
- lindex [btree_get_meta $::b1] 0
-} {4}
-do_test btree-8.24 {
- lindex [btree_pager_stats $::b1] 1
-} {2}
-#btree_pager_ref_dump $::b1
-do_test btree-8.25 {
- btree_integrity_check $::b1 1 2
-} {}
-
-# Check page splitting logic
-#
-do_test btree-9.1 {
- for {set i 1} {$i<=19} {incr i} {
- set key [format %03d $i]
- set data "*** $key *** $key *** $key *** $key ***"
- btree_insert $::c1 $key $data
- }
-} {}
-do_test btree-9.2 {
- btree_insert $::c1 020 {*** 020 *** 020 *** 020 *** 020 ***}
- select_keys $::c1
-} {001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020}
-
-# The previous "select_keys" command left the cursor pointing at the root
-# page. So there should only be two pages checked out. 2 (the root) and
-# page 1.
-do_test btree-9.2.1 {
- lindex [btree_pager_stats $::b1] 1
-} {2}
-for {set i 1} {$i<=20} {incr i} {
- do_test btree-9.3.$i.1 [subst {
- btree_move_to $::c1 [format %03d $i]
- btree_key $::c1
- }] [format %03d $i]
- do_test btree-9.3.$i.2 [subst {
- btree_move_to $::c1 [format %03d $i]
- string range \[btree_data $::c1\] 0 10
- }] "*** [format %03d $i] ***"
-}
-do_test btree-9.4.1 {
- lindex [btree_pager_stats $::b1] 1
-} {2}
-
-# Check the page joining logic.
-#
-#btree_page_dump $::b1 2
-#btree_pager_ref_dump $::b1
-do_test btree-9.4.2 {
- btree_move_to $::c1 005
- btree_delete $::c1
-} {}
-#btree_page_dump $::b1 2
-for {set i 1} {$i<=19} {incr i} {
- if {$i==5} continue
- do_test btree-9.5.$i.1 [subst {
- btree_move_to $::c1 [format %03d $i]
- btree_key $::c1
- }] [format %03d $i]
- do_test btree-9.5.$i.2 [subst {
- btree_move_to $::c1 [format %03d $i]
- string range \[btree_data $::c1\] 0 10
- }] "*** [format %03d $i] ***"
-}
-#btree_pager_ref_dump $::b1
-do_test btree-9.6 {
- btree_close_cursor $::c1
- lindex [btree_pager_stats $::b1] 1
-} {1}
-do_test btree-9.7 {
- btree_integrity_check $::b1 1 2
-} {}
-do_test btree-9.8 {
- btree_rollback $::b1
- lindex [btree_pager_stats $::b1] 1
-} {0}
-do_test btree-9.9 {
- btree_integrity_check $::b1 1 2
-} {}
-do_test btree-9.10 {
- btree_close $::b1
- set ::b1 [btree_open test1.bt 2000 0]
- btree_integrity_check $::b1 1 2
-} {}
-
-# Create a tree of depth two. That is, there is a single divider entry
-# on the root pages and two leaf pages. Then delete the divider entry
-# see what happens.
-#
-do_test btree-10.1 {
- btree_begin_transaction $::b1
- btree_clear_table $::b1 2
- lindex [btree_pager_stats $::b1] 1
-} {1}
-do_test btree-10.2 {
- set ::c1 [btree_cursor $::b1 2 1]
- lindex [btree_pager_stats $::b1] 1
-} {2}
-do_test btree-10.3 {
-btree_breakpoint
- for {set i 1} {$i<=30} {incr i} {
- set key [format %03d $i]
- set data "*** $key *** $key *** $key *** $key ***"
- btree_insert $::c1 $key $data
- }
- select_keys $::c1
-} {001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030}
-#btree_tree_dump $::b1 2
-do_test btree-10.4 {
- # The divider entry is 012. This is found by uncommenting the
- # btree_tree_dump call above and looking at the tree. If the page size
- # changes, this test will no longer work.
- btree_move_to $::c1 012
- btree_delete $::c1
- select_keys $::c1
-} {001 002 003 004 005 006 007 008 009 010 011 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030}
-#btree_pager_ref_dump $::b1
-#btree_tree_dump $::b1 2
-for {set i 1} {$i<=30} {incr i} {
- # Check the number of unreference pages. This should be 3 in most cases,
- # but 2 when the cursor is pointing to the divider entry which is now 013.
- do_test btree-10.5.$i {
- btree_move_to $::c1 [format %03d $i]
- lindex [btree_pager_stats $::b1] 1
- } [expr {$i==13?2:3}]
- #btree_pager_ref_dump $::b1
- #btree_tree_dump $::b1 2
-}
-
-# Create a tree with lots more pages
-#
-catch {unset ::data}
-catch {unset ::key}
-for {set i 31} {$i<=2000} {incr i} {
- do_test btree-11.1.$i.1 {
- set key [format %03d $i]
- set ::data "*** $key *** $key *** $key *** $key ***"
- btree_insert $::c1 $key $data
- btree_move_to $::c1 $key
- btree_key $::c1
- } [format %03d $i]
- do_test btree-11.1.$i.2 {
- btree_data $::c1
- } $::data
- set ::key [format %03d [expr {$i/2}]]
- if {$::key=="012"} {set ::key 013}
- do_test btree-11.1.$i.3 {
- btree_move_to $::c1 $::key
- btree_key $::c1
- } $::key
-}
-catch {unset ::data}
-catch {unset ::key}
-
-# Make sure our reference count is still correct.
-#
-do_test btree-11.2 {
- btree_close_cursor $::c1
- lindex [btree_pager_stats $::b1] 1
-} {1}
-do_test btree-11.3 {
- set ::c1 [btree_cursor $::b1 2 1]
- lindex [btree_pager_stats $::b1] 1
-} {2}
-
-# Delete the dividers on the root page
-#
-#btree_page_dump $::b1 2
-do_test btree-11.4 {
- btree_move_to $::c1 1667
- btree_delete $::c1
- btree_move_to $::c1 1667
- set k [btree_key $::c1]
- if {$k==1666} {
- set k [btree_next $::c1]
- }
- btree_key $::c1
-} {1668}
-#btree_page_dump $::b1 2
-
-# Change the data on an intermediate node such that the node becomes overfull
-# and has to split. We happen to know that intermediate nodes exist on
-# 337, 401 and 465 by the btree_page_dumps above
-#
-catch {unset ::data}
-set ::data {This is going to be a very long data segment}
-append ::data $::data
-append ::data $::data
-do_test btree-12.1 {
- btree_insert $::c1 337 $::data
- btree_move_to $::c1 337
- btree_data $::c1
-} $::data
-do_test btree-12.2 {
- btree_insert $::c1 401 $::data
- btree_move_to $::c1 401
- btree_data $::c1
-} $::data
-do_test btree-12.3 {
- btree_insert $::c1 465 $::data
- btree_move_to $::c1 465
- btree_data $::c1
-} $::data
-do_test btree-12.4 {
- btree_move_to $::c1 337
- btree_key $::c1
-} {337}
-do_test btree-12.5 {
- btree_data $::c1
-} $::data
-do_test btree-12.6 {
- btree_next $::c1
- btree_key $::c1
-} {338}
-do_test btree-12.7 {
- btree_move_to $::c1 464
- btree_key $::c1
-} {464}
-do_test btree-12.8 {
- btree_next $::c1
- btree_data $::c1
-} $::data
-do_test btree-12.9 {
- btree_next $::c1
- btree_key $::c1
-} {466}
-do_test btree-12.10 {
- btree_move_to $::c1 400
- btree_key $::c1
-} {400}
-do_test btree-12.11 {
- btree_next $::c1
- btree_data $::c1
-} $::data
-do_test btree-12.12 {
- btree_next $::c1
- btree_key $::c1
-} {402}
-# btree_commit $::b1
-# btree_tree_dump $::b1 1
-do_test btree-13.1 {
- btree_integrity_check $::b1 1 2
-} {}
-
-# To Do:
-#
-# 1. Do some deletes from the 3-layer tree
-# 2. Commit and reopen the database
-# 3. Read every 15th entry and make sure it works
-# 4. Implement btree_sanity and put it throughout this script
-#
-
-do_test btree-15.98 {
- btree_close_cursor $::c1
- lindex [btree_pager_stats $::b1] 1
-} {1}
-do_test btree-15.99 {
- btree_rollback $::b1
- lindex [btree_pager_stats $::b1] 1
-} {0}
-btree_pager_ref_dump $::b1
-
-# Miscellaneous tests.
-#
-# btree-16.1 - Check that a statement cannot be started if a transaction
-# is not active.
-# btree-16.2 - Check that it is an error to request more payload from a
-# btree entry than the entry contains.
-do_test btree-16.1 {
- catch {btree_begin_statement $::b1} msg
- set msg
-} SQLITE_ERROR
-
-do_test btree-16.2 {
- btree_begin_transaction $::b1
- set ::c1 [btree_cursor $::b1 2 1]
- btree_insert $::c1 1 helloworld
- btree_close_cursor $::c1
- btree_commit $::b1
-} {}
-do_test btree-16.3 {
- set ::c1 [btree_cursor $::b1 2 1]
- btree_first $::c1
-} 0
-do_test btree-16.4 {
- catch {btree_data $::c1 [expr [btree_payload_size $::c1] + 10]} msg
- set msg
-} SQLITE_ERROR
-
-if {$tcl_platform(platform)=="unix"} {
- do_test btree-16.5 {
- btree_close $::b1
- set ::origperm [file attributes test1.bt -permissions]
- file attributes test1.bt -permissions o-w,g-w,a-w
- set ::b1 [btree_open test1.bt 2000 0]
- catch {btree_cursor $::b1 2 1} msg
- file attributes test1.bt -permissions $::origperm
- btree_close $::b1
- set ::b1 [btree_open test1.bt 2000 0]
- set msg
- } {SQLITE_READONLY}
-}
-
-do_test btree-16.6 {
- set ::c1 [btree_cursor $::b1 2 1]
- set ::c2 [btree_cursor $::b1 2 1]
- btree_begin_transaction $::b1
- for {set i 0} {$i<100} {incr i} {
- btree_insert $::c1 $i [string repeat helloworld 10]
- }
- btree_last $::c2
- btree_insert $::c1 100 [string repeat helloworld 10]
-} {}
-
-do_test btree-16.7 {
- btree_close_cursor $::c1
- btree_close_cursor $::c2
- btree_commit $::b1
- set ::c1 [btree_cursor $::b1 2 1]
- catch {btree_insert $::c1 101 helloworld} msg
- set msg
-} {SQLITE_ERROR}
-do_test btree-16.8 {
- btree_first $::c1
- catch {btree_delete $::c1} msg
- set msg
-} {SQLITE_ERROR}
-do_test btree-16.9 {
- btree_close_cursor $::c1
- btree_begin_transaction $::b1
- set ::c1 [btree_cursor $::b1 2 0]
- catch {btree_insert $::c1 101 helloworld} msg
- set msg
-} {SQLITE_PERM}
-do_test btree-16.10 {
- catch {btree_delete $::c1} msg
- set msg
-} {SQLITE_PERM}
-
-# As of 2006-08-16 (version 3.3.7+) a read cursor will no
-# longer block a write cursor from the same database
-# connectiin. The following three tests uses to return
-# the SQLITE_LOCK error, but no more.
-#
-do_test btree-16.11 {
- btree_close_cursor $::c1
- set ::c2 [btree_cursor $::b1 2 1]
- set ::c1 [btree_cursor $::b1 2 0]
- catch {btree_insert $::c2 101 helloworld} msg
- set msg
-} {}
-do_test btree-16.12 {
- btree_first $::c2
- catch {btree_delete $::c2} msg
- set msg
-} {}
-do_test btree-16.13 {
- catch {btree_clear_table $::b1 2} msg
- set msg
-} {}
-
-
-do_test btree-16.14 {
- btree_close_cursor $::c1
- btree_close_cursor $::c2
- btree_commit $::b1
- catch {btree_clear_table $::b1 2} msg
- set msg
-} {SQLITE_ERROR}
-do_test btree-16.15 {
- catch {btree_drop_table $::b1 2} msg
- set msg
-} {SQLITE_ERROR}
-do_test btree-16.16 {
- btree_begin_transaction $::b1
- set ::c1 [btree_cursor $::b1 2 0]
- catch {btree_drop_table $::b1 2} msg
- set msg
-} {SQLITE_LOCKED}
-
-do_test btree-99.1 {
- btree_close $::b1
-} {}
-catch {unset data}
-catch {unset key}
-
-finish_test
+++ /dev/null
-# 2001 September 15
-#
-# The author disclaims copyright to this source code. In place of
-# a legal notice, here is a blessing:
-#
-# May you do good and not evil.
-# May you find forgiveness for yourself and forgive others.
-# May you share freely, never taking more than you give.
-#
-#***********************************************************************
-# This file implements regression tests for SQLite library. The
-# focus of this script is btree database backend
-#
-# $Id: btree2.test,v 1.15 2006/03/19 13:00:25 drh Exp $
-
-
-set testdir [file dirname $argv0]
-source $testdir/tester.tcl
-
-if {[info commands btree_open]!=""} {
-
-# Create a new database file containing no entries. The database should
-# contain 5 tables:
-#
-# 2 The descriptor table
-# 3 The foreground table
-# 4 The background table
-# 5 The long key table
-# 6 The long data table
-#
-# An explanation for what all these tables are used for is provided below.
-#
-do_test btree2-1.1 {
- expr srand(1)
- file delete -force test2.bt
- file delete -force test2.bt-journal
- set ::b [btree_open test2.bt 2000 0]
- btree_begin_transaction $::b
- btree_create_table $::b 0
-} {2}
-do_test btree2-1.2 {
- btree_create_table $::b 0
-} {3}
-do_test btree2-1.3 {
- btree_create_table $::b 0
-} {4}
-do_test btree2-1.4 {
- btree_create_table $::b 0
-} {5}
-do_test btree2-1.5 {
- btree_create_table $::b 0
-} {6}
-do_test btree2-1.6 {
- set ::c2 [btree_cursor $::b 2 1]
- btree_insert $::c2 {one} {1}
- btree_move_to $::c2 {one}
- btree_delete $::c2
- btree_close_cursor $::c2
- btree_commit $::b
- btree_integrity_check $::b 1 2 3 4 5 6
-} {}
-
-# This test module works by making lots of pseudo-random changes to a
-# database while simultaneously maintaining an invariant on that database.
-# Periodically, the script does a sanity check on the database and verifies
-# that the invariant is satisfied.
-#
-# The invariant is as follows:
-#
-# 1. The descriptor table always contains 2 enters. An entry keyed by
-# "N" is the number of elements in the foreground and background tables
-# combined. The entry keyed by "L" is the number of digits in the keys
-# for foreground and background tables.
-#
-# 2. The union of the foreground an background tables consists of N entries
-# 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.
-#
-# 3. Some entries in the foreground and background tables have keys that
-# begin with an L-digit number but are followed by additional characters.
-# For each such entry there is a corresponding entry in the long key
-# table. The long key table entry has a key which is just the L-digit
-# number and data which is the length of the key in the foreground and
-# background tables.
-#
-# 4. The data for both foreground and background entries is usually a
-# short string. But some entries have long data strings. For each
-# such entries there is an entry in the long data type. The key to
-# long data table is an L-digit number. (The extension on long keys
-# is omitted.) The data is the number of charaters in the data of the
-# foreground or background entry.
-#
-# The following function builds a database that satisfies all of the above
-# invariants.
-#
-proc build_db {N L} {
- for {set i 2} {$i<=6} {incr i} {
- catch {btree_close_cursor [set ::c$i]}
- btree_clear_table $::b $i
- set ::c$i [btree_cursor $::b $i 1]
- }
- btree_insert $::c2 N $N
- btree_insert $::c2 L $L
- set format %0${L}d
- for {set i 1} {$i<=$N} {incr i} {
- set key [format $format $i]
- set data $key
- btree_insert $::c3 $key $data
- }
-}
-
-# Given a base key number and a length, construct the full text of the key
-# or data.
-#
-proc make_payload {keynum L len} {
- set key [format %0${L}d $keynum]
- set r $key
- set i 1
- while {[string length $r]<$len} {
- append r " ($i) $key"
- incr i
- }
- return [string range $r 0 [expr {$len-1}]]
-}
-
-# Verify the invariants on the database. Return an empty string on
-# success or an error message if something is amiss.
-#
-proc check_invariants {} {
- set ck [btree_integrity_check $::b 1 2 3 4 5 6]
- if {$ck!=""} {
- puts "\n*** SANITY:\n$ck"
- exit
- return $ck
- }
- btree_move_to $::c3 {}
- btree_move_to $::c4 {}
- btree_move_to $::c2 N
- set N [btree_data $::c2]
- btree_move_to $::c2 L
- set L [btree_data $::c2]
- set LM1 [expr {$L-1}]
- for {set i 1} {$i<=$N} {incr i} {
- set key {}
- if {![btree_eof $::c3]} {
- set key [btree_key $::c3]
- }
- if {[scan $key %d k]<1} {set k 0}
- if {$k!=$i} {
- set key {}
- if {![btree_eof $::c4]} {
- set key [btree_key $::c4]
- }
- if {[scan $key %d k]<1} {set k 0}
- if {$k!=$i} {
- return "Key $i is missing from both foreground and background"
- }
- set data [btree_data $::c4]
- btree_next $::c4
- } else {
- set data [btree_data $::c3]
- btree_next $::c3
- }
- set skey [string range $key 0 $LM1]
- if {[btree_move_to $::c5 $skey]==0} {
- set keylen [btree_data $::c5]
- } else {
- set keylen $L
- }
- if {[string length $key]!=$keylen} {
- return "Key $i is the wrong size.\
- Is \"$key\" but should be \"[make_payload $k $L $keylen]\""
- }
- if {[make_payload $k $L $keylen]!=$key} {
- return "Key $i has an invalid extension"
- }
- if {[btree_move_to $::c6 $skey]==0} {
- set datalen [btree_data $::c6]
- } else {
- set datalen $L
- }
- if {[string length $data]!=$datalen} {
- return "Data for $i is the wrong size.\
- Is [string length $data] but should be $datalen"
- }
- if {[make_payload $k $L $datalen]!=$data} {
- return "Entry $i has an incorrect data"
- }
- }
-}
-
-# 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.
-# the entry with that key is put in the foreground table with probability
-# $I and it is put in background with probability (1.0-$I). It gets
-# a long key with probability $K and long data with probability $D.
-#
-set chngcnt 0
-proc random_changes {n I K D} {
- global chngcnt
- btree_move_to $::c2 N
- set N [btree_data $::c2]
- btree_move_to $::c2 L
- set L [btree_data $::c2]
- set LM1 [expr {$L-1}]
- set total [expr {int($N*$n)}]
- set format %0${L}d
- for {set i 0} {$i<$total} {incr i} {
- set k [expr {int(rand()*$N)+1}]
- set insert [expr {rand()<=$I}]
- set longkey [expr {rand()<=$K}]
- set longdata [expr {rand()<=$D}]
- if {$longkey} {
- set x [expr {rand()}]
- set keylen [expr {int($x*$x*$x*$x*3000)+10}]
- } else {
- set keylen $L
- }
- set key [make_payload $k $L $keylen]
- if {$longdata} {
- set x [expr {rand()}]
- set datalen [expr {int($x*$x*$x*$x*3000)+10}]
- } else {
- set datalen $L
- }
- set data [make_payload $k $L $datalen]
- set basekey [format $format $k]
- if {[set c [btree_move_to $::c3 $basekey]]==0} {
- btree_delete $::c3
- } else {
- if {$c<0} {btree_next $::c3}
- if {![btree_eof $::c3]} {
- if {[string match $basekey* [btree_key $::c3]]} {
- btree_delete $::c3
- }
- }
- }
- if {[set c [btree_move_to $::c4 $basekey]]==0} {
- btree_delete $::c4
- } else {
- if {$c<0} {btree_next $::c4}
- if {![btree_eof $::c4]} {
- if {[string match $basekey* [btree_key $::c4]]} {
- btree_delete $::c4
- }
- }
- }
- set kx -1
- if {![btree_eof $::c4]} {
- if {[scan [btree_key $::c4] %d kx]<1} {set kx -1}
- }
- if {$kx==$k} {
- btree_delete $::c4
- }
- # For debugging - change the "0" to "1" to integrity check after
- # every change.
- if 0 {
- incr chngcnt
- puts check----$chngcnt
- set ck [btree_integrity_check $::b 1 2 3 4 5 6]
- if {$ck!=""} {
- puts "\nSANITY CHECK FAILED!\n$ck"
- exit
- }
- }
- if {$insert} {
- btree_insert $::c3 $key $data
- } else {
- btree_insert $::c4 $key $data
- }
- if {$longkey} {
- btree_insert $::c5 $basekey $keylen
- } elseif {[btree_move_to $::c5 $basekey]==0} {
- btree_delete $::c5
- }
- if {$longdata} {
- btree_insert $::c6 $basekey $datalen
- } elseif {[btree_move_to $::c6 $basekey]==0} {
- btree_delete $::c6
- }
- # For debugging - change the "0" to "1" to integrity check after
- # every change.
- if 0 {
- incr chngcnt
- puts check----$chngcnt
- set ck [btree_integrity_check $::b 1 2 3 4 5 6]
- if {$ck!=""} {
- puts "\nSANITY CHECK FAILED!\n$ck"
- exit
- }
- }
- }
-}
-set btree_trace 0
-
-# Repeat this test sequence on database of various sizes
-#
-set testno 2
-foreach {N L} {
- 10 2
- 50 2
- 200 3
- 2000 5
-} {
- puts "**** N=$N L=$L ****"
- set hash [md5file test2.bt]
- do_test btree2-$testno.1 [subst -nocommands {
- set ::c2 [btree_cursor $::b 2 1]
- set ::c3 [btree_cursor $::b 3 1]
- set ::c4 [btree_cursor $::b 4 1]
- set ::c5 [btree_cursor $::b 5 1]
- set ::c6 [btree_cursor $::b 6 1]
- btree_begin_transaction $::b
- build_db $N $L
- check_invariants
- }] {}
- do_test btree2-$testno.2 {
- btree_close_cursor $::c2
- btree_close_cursor $::c3
- btree_close_cursor $::c4
- btree_close_cursor $::c5
- btree_close_cursor $::c6
- btree_rollback $::b
- md5file test2.bt
- } $hash
- do_test btree2-$testno.3 [subst -nocommands {
- btree_begin_transaction $::b
- set ::c2 [btree_cursor $::b 2 1]
- set ::c3 [btree_cursor $::b 3 1]
- set ::c4 [btree_cursor $::b 4 1]
- set ::c5 [btree_cursor $::b 5 1]
- set ::c6 [btree_cursor $::b 6 1]
- build_db $N $L
- check_invariants
- }] {}
- do_test btree2-$testno.4 {
- btree_commit $::b
- check_invariants
- } {}
- do_test btree2-$testno.5 {
- lindex [btree_pager_stats $::b] 1
- } {6}
- do_test btree2-$testno.6 {
- btree_cursor_info $::c2
- btree_cursor_info $::c3
- btree_cursor_info $::c4
- btree_cursor_info $::c5
- btree_cursor_info $::c6
- btree_close_cursor $::c2
- btree_close_cursor $::c3
- btree_close_cursor $::c4
- btree_close_cursor $::c5
- btree_close_cursor $::c6
- lindex [btree_pager_stats $::b] 1
- } {0}
- do_test btree2-$testno.7 {
- btree_close $::b
- } {}
-
- # For each database size, run various changes tests.
- #
- set num2 1
- foreach {n I K D} {
- 0.5 0.5 0.1 0.1
- 1.0 0.2 0.1 0.1
- 1.0 0.8 0.1 0.1
- 2.0 0.0 0.1 0.1
- 2.0 1.0 0.1 0.1
- 2.0 0.0 0.0 0.0
- 2.0 1.0 0.0 0.0
- } {
- set testid btree2-$testno.8.$num2
- set hash [md5file test2.bt]
- do_test $testid.0 {
- set ::b [btree_open test2.bt 2000 0]
- set ::c2 [btree_cursor $::b 2 1]
- set ::c3 [btree_cursor $::b 3 1]
- set ::c4 [btree_cursor $::b 4 1]
- set ::c5 [btree_cursor $::b 5 1]
- set ::c6 [btree_cursor $::b 6 1]
- check_invariants
- } {}
- set cnt 6
- for {set i 2} {$i<=6} {incr i} {
- if {[lindex [btree_cursor_info [set ::c$i]] 0]!=$i} {incr cnt}
- }
- do_test $testid.1 {
- btree_begin_transaction $::b
- lindex [btree_pager_stats $::b] 1
- } $cnt
- do_test $testid.2 [subst {
- random_changes $n $I $K $D
- }] {}
- do_test $testid.3 {
- check_invariants
- } {}
- do_test $testid.4 {
- btree_close_cursor $::c2
- btree_close_cursor $::c3
- btree_close_cursor $::c4
- btree_close_cursor $::c5
- btree_close_cursor $::c6
- btree_rollback $::b
- md5file test2.bt
- } $hash
- btree_begin_transaction $::b
- set ::c2 [btree_cursor $::b 2 1]
- set ::c3 [btree_cursor $::b 3 1]
- set ::c4 [btree_cursor $::b 4 1]
- set ::c5 [btree_cursor $::b 5 1]
- set ::c6 [btree_cursor $::b 6 1]
- do_test $testid.5 [subst {
- random_changes $n $I $K $D
- }] {}
- do_test $testid.6 {
- check_invariants
- } {}
- do_test $testid.7 {
- btree_commit $::b
- check_invariants
- } {}
- set hash [md5file test2.bt]
- do_test $testid.8 {
- btree_close_cursor $::c2
- btree_close_cursor $::c3
- btree_close_cursor $::c4
- btree_close_cursor $::c5
- btree_close_cursor $::c6
- lindex [btree_pager_stats $::b] 1
- } {0}
- do_test $testid.9 {
- btree_close $::b
- set ::b [btree_open test2.bt 2000 0]
- set ::c2 [btree_cursor $::b 2 1]
- set ::c3 [btree_cursor $::b 3 1]
- set ::c4 [btree_cursor $::b 4 1]
- set ::c5 [btree_cursor $::b 5 1]
- set ::c6 [btree_cursor $::b 6 1]
- check_invariants
- } {}
- do_test $testid.10 {
- btree_close_cursor $::c2
- btree_close_cursor $::c3
- btree_close_cursor $::c4
- btree_close_cursor $::c5
- btree_close_cursor $::c6
- lindex [btree_pager_stats $::b] 1
- } {0}
- do_test $testid.11 {
- btree_close $::b
- } {}
- incr num2
- }
- incr testno
- set ::b [btree_open test2.bt 2000 0]
-}
-
-# Testing is complete. Shut everything down.
-#
-do_test btree-999.1 {
- lindex [btree_pager_stats $::b] 1
-} {0}
-do_test btree-999.2 {
- btree_close $::b
-} {}
-do_test btree-999.3 {
- file delete -force test2.bt
- file exists test2.bt-journal
-} {0}
-
-} ;# end if( not mem: and has pager_open command );
-
-finish_test
+++ /dev/null
-# 2002 December 03
-#
-# The author disclaims copyright to this source code. In place of
-# a legal notice, here is a blessing:
-#
-# May you do good and not evil.
-# May you find forgiveness for yourself and forgive others.
-# May you share freely, never taking more than you give.
-#
-#***********************************************************************
-# This file implements regression tests for SQLite library. The
-# focus of this script is btree database backend
-#
-# This file focuses on testing the sqliteBtreeNext() and
-# sqliteBtreePrevious() procedures and making sure they are able
-# to step through an entire table from either direction.
-#
-# $Id: btree4.test,v 1.2 2004/05/09 20:40:12 drh Exp $
-
-
-set testdir [file dirname $argv0]
-source $testdir/tester.tcl
-
-if {[info commands btree_open]!=""} {
-
-# Open a test database.
-#
-file delete -force test1.bt
-file delete -force test1.bt-journal
-set b1 [btree_open test1.bt 2000 0]
-btree_begin_transaction $b1
-do_test btree4-0.1 {
- btree_create_table $b1 0
-} 2
-
-set data {abcdefghijklmnopqrstuvwxyz0123456789}
-append data $data
-append data $data
-append data $data
-append data $data
-
-foreach N {10 100 1000} {
- btree_clear_table $::b1 2
- set ::c1 [btree_cursor $::b1 2 1]
- do_test btree4-$N.1 {
- for {set i 1} {$i<=$N} {incr i} {
- btree_insert $::c1 [format k-%05d $i] $::data-$i
- }
- btree_first $::c1
- btree_key $::c1
- } {k-00001}
- do_test btree4-$N.2 {
- btree_data $::c1
- } $::data-1
- for {set i 2} {$i<=$N} {incr i} {
- do_test btree-$N.3.$i.1 {
- btree_next $::c1
- } 0
- do_test btree-$N.3.$i.2 {
- btree_key $::c1
- } [format k-%05d $i]
- do_test btree-$N.3.$i.3 {
- btree_data $::c1
- } $::data-$i
- }
- do_test btree4-$N.4 {
- btree_next $::c1
- } 1
- do_test btree4-$N.5 {
- btree_last $::c1
- } 0
- do_test btree4-$N.6 {
- btree_key $::c1
- } [format k-%05d $N]
- do_test btree4-$N.7 {
- btree_data $::c1
- } $::data-$N
- for {set i [expr {$N-1}]} {$i>=1} {incr i -1} {
- do_test btree4-$N.8.$i.1 {
- btree_prev $::c1
- } 0
- do_test btree4-$N.8.$i.2 {
- btree_key $::c1
- } [format k-%05d $i]
- do_test btree4-$N.8.$i.3 {
- btree_data $::c1
- } $::data-$i
- }
- do_test btree4-$N.9 {
- btree_prev $::c1
- } 1
- btree_close_cursor $::c1
-}
-
-btree_rollback $::b1
-btree_pager_ref_dump $::b1
-btree_close $::b1
-
-} ;# end if( not mem: and has pager_open command );
-
-finish_test
+++ /dev/null
-# 2004 May 10
-#
-# The author disclaims copyright to this source code. In place of
-# a legal notice, here is a blessing:
-#
-# May you do good and not evil.
-# May you find forgiveness for yourself and forgive others.
-# May you share freely, never taking more than you give.
-#
-#***********************************************************************
-# This file implements regression tests for SQLite library. The
-# focus of this script is btree database backend
-#
-# $Id: btree5.test,v 1.5 2004/05/14 12:17:46 drh Exp $
-
-
-set testdir [file dirname $argv0]
-source $testdir/tester.tcl
-
-# Attempting to read table 1 of an empty file gives an SQLITE_EMPTY
-# error.
-#
-do_test btree5-1.1 {
- file delete -force test1.bt
- file delete -force test1.bt-journal
- set rc [catch {btree_open test1.bt 2000 0} ::b1]
-} {0}
-do_test btree5-1.2 {
- set rc [catch {btree_cursor $::b1 1 0} ::c1]
-} {1}
-do_test btree5-1.3 {
- set ::c1
-} {SQLITE_EMPTY}
-do_test btree5-1.4 {
- set rc [catch {btree_cursor $::b1 1 1} ::c1]
-} {1}
-do_test btree5-1.5 {
- set ::c1
-} {SQLITE_EMPTY}
-
-# Starting a transaction initializes the first page of the database
-# and the error goes away.
-#
-do_test btree5-1.6 {
- btree_begin_transaction $b1
- set rc [catch {btree_cursor $b1 1 0} c1]
-} {0}
-do_test btree5-1.7 {
- btree_first $c1
-} {1}
-do_test btree5-1.8 {
- btree_close_cursor $c1
- btree_rollback $b1
- set rc [catch {btree_cursor $b1 1 0} c1]
-} {1}
-do_test btree5-1.9 {
- set c1
-} {SQLITE_EMPTY}
-do_test btree5-1.10 {
- btree_begin_transaction $b1
- set rc [catch {btree_cursor $b1 1 0} c1]
-} {0}
-do_test btree5-1.11 {
- btree_first $c1
-} {1}
-do_test btree5-1.12 {
- btree_close_cursor $c1
- btree_commit $b1
- set rc [catch {btree_cursor $b1 1 0} c1]
-} {0}
-do_test btree5-1.13 {
- btree_first $c1
-} {1}
-do_test btree5-1.14 {
- btree_close_cursor $c1
- btree_integrity_check $b1 1
-} {}
-
-# Insert many entries into table 1. This is designed to test the
-# virtual-root logic that comes into play for page one. It is also
-# a good test of INTKEY tables.
-#
-# Stagger the inserts. After the inserts complete, go back and do
-# deletes. Stagger the deletes too. Repeat this several times.
-#
-
-# Do N inserts into table 1 using random keys between 0 and 1000000
-#
-proc random_inserts {N} {
- global c1
- while {$N>0} {
- set k [expr {int(rand()*1000000)}]
- if {[btree_move_to $c1 $k]==0} continue; # entry already exists
- btree_insert $c1 $k data-for-$k
- incr N -1
- }
-}
-
-# Do N delete from table 1
-#
-proc random_deletes {N} {
- global c1
- while {$N>0} {
- set k [expr {int(rand()*1000000)}]
- btree_move_to $c1 $k
- btree_delete $c1
- incr N -1
- }
-}
-
-# Make sure the table has exactly N entries. Make sure the data for
-# each entry agrees with its key.
-#
-proc check_table {N} {
- global c1
- btree_first $c1
- set cnt 0
- while {![btree_eof $c1]} {
- if {[set data [btree_data $c1]] ne "data-for-[btree_key $c1]"} {
- return "wrong data for entry $cnt"
- }
- set n [string length $data]
- set fdata1 [btree_fetch_data $c1 $n]
- set fdata2 [btree_fetch_data $c1 -1]
- if {$fdata1 ne "" && $fdata1 ne $data} {
- return "DataFetch returned the wrong value with amt=$n"
- }
- if {$fdata1 ne $fdata2} {
- return "DataFetch returned the wrong value when amt=-1"
- }
- if {$n>10} {
- set fdata3 [btree_fetch_data $c1 10]
- if {$fdata3 ne [string range $data 0 9]} {
- return "DataFetch returned the wrong value when amt=10"
- }
- }
- incr cnt
- btree_next $c1
- }
- if {$cnt!=$N} {
- return "wrong number of entries"
- }
- return {}
-}
-
-# Initialize the database
-#
-btree_begin_transaction $b1
-set c1 [btree_cursor $b1 1 1]
-set btree_trace 0
-
-# Do the tests.
-#
-set cnt 0
-for {set i 1} {$i<=100} {incr i} {
- do_test btree5-2.$i.1 {
- random_inserts 200
- incr cnt 200
- check_table $cnt
- } {}
- do_test btree5-2.$i.2 {
- btree_integrity_check $b1 1
- } {}
- do_test btree5-2.$i.3 {
- random_deletes 190
- incr cnt -190
- check_table $cnt
- } {}
- do_test btree5-2.$i.4 {
- btree_integrity_check $b1 1
- } {}
-}
-
-#btree_tree_dump $b1 1
-btree_close_cursor $c1
-btree_commit $b1
-btree_begin_transaction $b1
-
-# This procedure converts an integer into a variable-length text key.
-# The conversion is reversible.
-#
-# The first two characters of the string are alphabetics derived from
-# the least significant bits of the number. Because they are derived
-# from least significant bits, the sort order of the resulting string
-# is different from numeric order. After the alphabetic prefix comes
-# the original number. A variable-length suffix follows. The length
-# of the suffix is based on a hash of the original number.
-#
-proc num_to_key {n} {
- global charset ncharset suffix
- set c1 [string index $charset [expr {$n%$ncharset}]]
- set c2 [string index $charset [expr {($n/$ncharset)%$ncharset}]]
- set nsuf [expr {($n*211)%593}]
- return $c1$c2-$n-[string range $suffix 0 $nsuf]
-}
-set charset {abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ}
-set ncharset [string length $charset]
-set suffix $charset$charset
-while {[string length $suffix]<1000} {append suffix $suffix}
-
-# This procedures extracts the original integer used to create
-# a key by num_to_key
-#
-proc key_to_num {key} {
- regexp {^..-([0-9]+)} $key all n
- return $n
-}
-
-# Insert into table $tab keys corresponding to all values between
-# $start and $end, inclusive.
-#
-proc insert_range {tab start end} {
- for {set i $start} {$i<=$end} {incr i} {
- btree_insert $tab [num_to_key $i] {}
- }
-}
-
-# Delete from table $tab keys corresponding to all values between
-# $start and $end, inclusive.
-#
-proc delete_range {tab start end} {
- for {set i $start} {$i<=$end} {incr i} {
- if {[btree_move_to $tab [num_to_key $i]]==0} {
- btree_delete $tab
- }
- }
-}
-
-# Make sure table $tab contains exactly those keys corresponding
-# to values between $start and $end
-#
-proc check_range {tab start end} {
- btree_first $tab
- while {![btree_eof $tab]} {
- set key [btree_key $tab]
- set i [key_to_num $key]
- if {[num_to_key $i] ne $key} {
- return "malformed key: $key"
- }
- set got($i) 1
- btree_next $tab
- }
- set all [lsort -integer [array names got]]
- if {[llength $all]!=$end+1-$start} {
- return "table contains wrong number of values"
- }
- if {[lindex $all 0]!=$start} {
- return "wrong starting value"
- }
- if {[lindex $all end]!=$end} {
- return "wrong ending value"
- }
- return {}
-}
-
-# Create a zero-data table and test it out.
-#
-do_test btree5-3.1 {
- set rc [catch {btree_create_table $b1 2} t2]
-} {0}
-do_test btree5-3.2 {
- set rc [catch {btree_cursor $b1 $t2 1} c2]
-} {0}
-set start 1
-set end 100
-for {set i 1} {$i<=100} {incr i} {
- do_test btree5-3.3.$i.1 {
- insert_range $c2 $start $end
- btree_integrity_check $b1 1 $t2
- } {}
- do_test btree5-3.3.$i.2 {
- check_range $c2 $start $end
- } {}
- set nstart $start
- incr nstart 89
- do_test btree5-3.3.$i.3 {
- delete_range $c2 $start $nstart
- btree_integrity_check $b1 1 $t2
- } {}
- incr start 90
- do_test btree5-3.3.$i.4 {
- check_range $c2 $start $end
- } {}
- incr end 100
-}
-
-
-btree_close_cursor $c2
-btree_commit $b1
-btree_close $b1
-
-finish_test
+++ /dev/null
-# 2004 May 10
-#
-# The author disclaims copyright to this source code. In place of
-# a legal notice, here is a blessing:
-#
-# May you do good and not evil.
-# May you find forgiveness for yourself and forgive others.
-# May you share freely, never taking more than you give.
-#
-#***********************************************************************
-# This file implements regression tests for SQLite library. The
-# focus of this script is btree database backend - specifically
-# the B+tree tables. B+trees store all data on the leaves rather
-# that storing data with keys on interior nodes.
-#
-# $Id: btree6.test,v 1.4 2004/05/20 22:16:31 drh Exp $
-
-
-set testdir [file dirname $argv0]
-source $testdir/tester.tcl
-
-
-# Insert many entries into the table that cursor $cur points to.
-# The table should be an INTKEY table.
-#
-# Stagger the inserts. After the inserts complete, go back and do
-# deletes. Stagger the deletes too. Repeat this several times.
-#
-
-# Do N inserts into table $tab using random keys between 0 and 1000000
-#
-proc random_inserts {cur N} {
- global inscnt
- while {$N>0} {
- set k [expr {int(rand()*1000000)}]
- if {[btree_move_to $cur $k]==0} {
- continue; # entry already exists
- }
- incr inscnt
- btree_insert $cur $k data-for-$k
- incr N -1
- }
-}
-set inscnt 0
-
-# Do N delete from the table that $cur points to.
-#
-proc random_deletes {cur N} {
- while {$N>0} {
- set k [expr {int(rand()*1000000)}]
- btree_move_to $cur $k
- btree_delete $cur
- incr N -1
- }
-}
-
-# Make sure the table that $cur points to has exactly N entries.
-# Make sure the data for each entry agrees with its key.
-#
-proc check_table {cur N} {
- btree_first $cur
- set cnt 0
- while {![btree_eof $cur]} {
- if {[set data [btree_data $cur]] ne "data-for-[btree_key $cur]"} {
- return "wrong data for entry $cnt"
- }
- set n [string length $data]
- set fdata1 [btree_fetch_data $cur $n]
- set fdata2 [btree_fetch_data $cur -1]
- if {$fdata1 ne "" && $fdata1 ne $data} {
- return "DataFetch returned the wrong value with amt=$n"
- }
- if {$fdata1 ne $fdata2} {
- return "DataFetch returned the wrong value when amt=-1"
- }
- if {$n>10} {
- set fdata3 [btree_fetch_data $cur 10]
- if {$fdata3 ne [string range $data 0 9]} {
- return "DataFetch returned the wrong value when amt=10"
- }
- }
- incr cnt
- btree_next $cur
- }
- if {$cnt!=$N} {
- return "wrong number of entries. Got $cnt. Looking for $N"
- }
- return {}
-}
-
-# Initialize the database
-#
-file delete -force test1.bt
-file delete -force test1.bt-journal
-set b1 [btree_open test1.bt 2000 0]
-btree_begin_transaction $b1
-set tab [btree_create_table $b1 5]
-set cur [btree_cursor $b1 $tab 1]
-set btree_trace 0
-expr srand(1)
-
-# Do the tests.
-#
-set cnt 0
-for {set i 1} {$i<=40} {incr i} {
- do_test btree6-1.$i.1 {
- random_inserts $cur 200
- incr cnt 200
- check_table $cur $cnt
- } {}
- do_test btree6-1.$i.2 {
- btree_integrity_check $b1 1 $tab
- } {}
- do_test btree6-1.$i.3 {
- random_deletes $cur 90
- incr cnt -90
- check_table $cur $cnt
- } {}
- do_test btree6-1.$i.4 {
- btree_integrity_check $b1 1 $tab
- } {}
-}
-
-btree_close_cursor $cur
-btree_commit $b1
-btree_close $b1
-
-finish_test
+++ /dev/null
-# 2004 Jun 4
-#
-# The author disclaims copyright to this source code. In place of
-# a legal notice, here is a blessing:
-#
-# May you do good and not evil.
-# May you find forgiveness for yourself and forgive others.
-# May you share freely, never taking more than you give.
-#
-#***********************************************************************
-# This file implements regression tests for SQLite library. The
-# focus of this script is btree database backend.
-#
-# $Id: btree7.test,v 1.2 2004/11/04 14:47:13 drh Exp $
-
-
-set testdir [file dirname $argv0]
-source $testdir/tester.tcl
-
-# Stress the balance routine by trying to create situations where
-# 3 neighboring nodes split into 5.
-#
-set bigdata _123456789 ;# 10
-append bigdata $bigdata ;# 20
-append bigdata $bigdata ;# 40
-append bigdata $bigdata ;# 80
-append bigdata $bigdata ;# 160
-append bigdata $bigdata ;# 320
-append bigdata $bigdata ;# 640
-set data450 [string range $bigdata 0 449]
-do_test btree7-1.1 {
- execsql "
- CREATE TABLE t1(x INTEGER PRIMARY KEY, y TEXT);
- INSERT INTO t1 VALUES(1, '$bigdata');
- INSERT INTO t1 VALUES(2, '$bigdata');
- INSERT INTO t1 VALUES(3, '$data450');
- INSERT INTO t1 VALUES(5, '$data450');
- INSERT INTO t1 VALUES(8, '$bigdata');
- INSERT INTO t1 VALUES(9, '$bigdata');
- "
-} {}
-integrity_check btree7-1.2
-do_test btree7-1.3 {
- execsql "
- INSERT INTO t1 VALUES(4, '$bigdata');
- "
-} {}
-integrity_check btree7-1.4
-
-finish_test
+++ /dev/null
-# 2005 August 2
-#
-# The author disclaims copyright to this source code. In place of
-# a legal notice, here is a blessing:
-#
-# May you do good and not evil.
-# May you find forgiveness for yourself and forgive others.
-# May you share freely, never taking more than you give.
-#
-#***********************************************************************
-# This file implements regression tests for SQLite library. The
-# focus of this script is btree database backend.
-#
-# $Id: btree8.test,v 1.6 2005/08/02 17:13:12 drh Exp $
-
-set testdir [file dirname $argv0]
-source $testdir/tester.tcl
-
-# Ticket #1346: If the table rooted on page 1 contains a single entry
-# and that single entries has to flow out into another page because
-# page 1 is 100-bytes smaller than most other pages, then you delete that
-# one entry, everything should still work.
-#
-do_test btree8-1.1 {
- execsql {
-CREATE TABLE t1(x
- ----------------------------------------------------------------------------
- ----------------------------------------------------------------------------
- ----------------------------------------------------------------------------
- ----------------------------------------------------------------------------
- ----------------------------------------------------------------------------
- ----------------------------------------------------------------------------
- ----------------------------------------------------------------------------
- ----------------------------------------------------------------------------
- ----------------------------------------------------------------------------
- ----------------------------------------------------------------------------
- ----------------------------------------------------------------------------
- ----------------------------------------------------------------------------
-);
-DROP table t1;
- }
-} {}
-integrity_check btree8-1.2
+++ /dev/null
-# 2007 May 01
-#
-# The author disclaims copyright to this source code. In place of
-# a legal notice, here is a blessing:
-#
-# May you do good and not evil.
-# May you find forgiveness for yourself and forgive others.
-# May you share freely, never taking more than you give.
-#
-#***********************************************************************
-# This file implements regression tests for SQLite library. The
-# focus of this script is btree database backend.
-#
-# $Id: btree9.test,v 1.1 2007/05/02 01:34:32 drh Exp $
-
-set testdir [file dirname $argv0]
-source $testdir/tester.tcl
-
-# The sqlite3BtreeInsert() API now has an additional "nZero" parameter
-# which specifies the number of zero bytes to append to the end of the
-# data. This feature allows large zero-filled BLOBs to be created without
-# having to allocate a big chunk of memory to instantiate the blob.
-#
-# The following code tests the new feature.
-#
-
-# Create the database
-#
-do_test btree9-1.1 {
- file delete -force test1.bt
- file delete -force test1.bt-journal
- set b1 [btree_open test1.bt 2000 0]
- btree_begin_transaction $b1
- set t1 [btree_create_table $b1 5]
- set c1 [btree_cursor $b1 $t1 1]
- btree_insert $c1 1 data-for-1 20000
- btree_move_to $c1 1
- btree_key $c1
-} {1}
-do_test btree9-1.2 {
- btree_payload_size $c1
-} {20010}
-
-
-btree_close_cursor $c1
-btree_commit $b1
-btree_close $b1
-
-finish_test
#***********************************************************************
# This file runs all tests.
#
-# $Id: quick.test,v 1.72 2008/03/22 01:08:01 drh Exp $
+# $Id: quick.test,v 1.73 2008/03/25 00:22:22 drh Exp $
proc lshift {lvar} {
upvar $lvar l
all.test
async.test
async2.test
- btree2.test
- btree3.test
- btree4.test
- btree5.test
- btree6.test
corrupt.test
crash.test
crash2.test