]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Pager tests working. (CVS 1308)
authordrh <drh@noemail.net>
Mon, 26 Apr 2004 14:10:20 +0000 (14:10 +0000)
committerdrh <drh@noemail.net>
Mon, 26 Apr 2004 14:10:20 +0000 (14:10 +0000)
FossilOrigin-Name: 910067a200c4b25b5d813a84146673d3d1c80952

14 files changed:
main.mk
manifest
manifest.uuid
src/btree.c
src/btree.h
src/md5.c
src/pager.c
src/pager.h
src/sqliteInt.h
src/tclsqlite.c
src/test2.c
src/util.c
test/pager.test
test/tester.tcl

diff --git a/main.mk b/main.mk
index 2d9f0be50207a5183180f976bf9d1dbb695a4465..120167bd0f7951af12e62c13325925510040a632 100644 (file)
--- a/main.mk
+++ b/main.mk
@@ -54,7 +54,10 @@ TCCX = $(TCC) $(OPTS) $(THREADSAFE) $(USLEEP) -I. -I$(TOP)/src
 
 # Object files for the SQLite library.
 #
-LIBOBJ = attach.o auth.o btree.o btree_rb.o build.o copy.o date.o delete.o \
+LIBOBJ = hash.o os.o pager.o random.o \
+         util.o tclsqlite.o
+
+LIBOBJ_ORIG = attach.o auth.o btree.o btree_rb.o build.o copy.o date.o delete.o \
          expr.o func.o hash.o insert.o \
          main.o opcodes.o os.o pager.o parse.o pragma.o printf.o random.o \
          select.o table.o tokenize.o trigger.o update.o util.o \
@@ -63,6 +66,15 @@ LIBOBJ = attach.o auth.o btree.o btree_rb.o build.o copy.o date.o delete.o \
 # All of the source code files.
 #
 SRC = \
+  $(TOP)/src/hash.c \
+  $(TOP)/src/hash.h \
+  $(TOP)/src/os.c \
+  $(TOP)/src/pager.c \
+  $(TOP)/src/pager.h \
+  $(TOP)/src/random.c \
+  $(TOP)/src/util.c 
+
+SRC_ORIG = \
   $(TOP)/src/attach.c \
   $(TOP)/src/auth.c \
   $(TOP)/src/btree.c \
@@ -106,6 +118,12 @@ SRC = \
 # Source code to the test files.
 #
 TESTSRC = \
+  $(TOP)/src/os.c \
+  $(TOP)/src/pager.c \
+  $(TOP)/src/test2.c \
+  $(TOP)/src/md5.c
+
+TESTSRC_ORIG = \
   $(TOP)/src/btree.c \
   $(TOP)/src/func.c \
   $(TOP)/src/os.c \
index faa9ebfcc0068dbff4faa30eeebdc67bcbcab51d..56938aa9e933bd96a1e19c7f81a6f90d0d0ac3fe 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Begin\smodifying\sthe\sBTree\scode\sfor\sthe\snew\sversion-3\sfile\sformat.\nThis\sis\sa\swork-in-progress.\nAs\sof\sthis\scheck-in,\sSQLite\swill\snot\sbuild.\s(CVS\s1306)
-D 2004-04-23T23:43:10
+C Pager\stests\sworking.\s(CVS\s1308)
+D 2004-04-26T14:10:21
 F Makefile.in ab7b0d5118e2da97bac66be8684a1034e3500f5a
 F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
 F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
@@ -15,7 +15,7 @@ F doc/lemon.html f0f682f50210928c07e562621c3b7e8ab912a538
 F doc/report1.txt a031aaf37b185e4fa540223cb516d3bccec7eeac
 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895
 F ltmain.sh f6b283068efa69f06eb8aa1fe4bddfdbdeb35826
-F main.mk 1b27efb94be53a96c4333584a00a59fcc87ddc37
+F main.mk 1318f38db512abb0abdbdf4d3c9dd213e2960977
 F publish.sh 1cd5c982388560fa91eedf6a338e210f713b35c8
 F spec.template a38492f1c1dd349fc24cb0565e08afc53045304b
 F sqlite.1 83f4a9d37bdf2b7ef079a82d54eaf2e3509ee6ea
@@ -23,8 +23,8 @@ F sqlite.def fc4f5734786fe4743cfe2aa98eb2da4b089edb5f
 F sqlite.pc.in 30552343140c53304c2a658c080fbe810cd09ca2
 F src/attach.c b01db0d3211f673d8e670abf7eaad04591d40d14
 F src/auth.c 4fa3b05bd19445d1c474d6751c4a508d6ea0abe1
-F src/btree.c cb9836c17b6d8ee447627caaf614ca97b5dc1188
-F src/btree.h 41cb3ff6ebc3f6da2d0a074e39ff8c7a2287469f
+F src/btree.c 4e2b50ae03bd4d9e678bda14b08307d80dd4471c
+F src/btree.h 858659c6605ae07a2a0fb3d176b25573d30f27c5
 F src/btree_rb.c 99feb3ff835106d018a483a1ce403e5cf9c718bc
 F src/build.c 76fbca30081decd6615dee34b48c927ed5063752
 F src/copy.c 750e13828c3e4a293123e36aaa7cf0f22466248a
@@ -37,11 +37,11 @@ F src/hash.c 9b56ef3b291e25168f630d5643a4264ec011c70e
 F src/hash.h 3247573ab95b9dd90bcca0307a75d9a16da1ccc7
 F src/insert.c c0485ee2d1b99322894e2d1e0b576fd05ed75616
 F src/main.c 94dd355768e2a389e184a069b6880f4bac100307
-F src/md5.c fe4f9c9c6f71dfc26af8da63e4d04489b1430565
+F src/md5.c c53e7b50418afbde22d07128baf3cc615530e846
 F src/os.c 5f11382733805d4529ec2a30800e117f30995ea8
 F src/os.h 250a3789be609adfee5c5aa20137ce8683276f24
-F src/pager.c b246986e5ba31b15aa3cf91d3b9ec2e608aceb8e
-F src/pager.h 82332878799280145639a48d88cdb4058925e3f6
+F src/pager.c 2e3af839e7aab5bfaff7a0ef4694bae487b0ffeb
+F src/pager.h 138ca7f73c47bebf469591939dcefa934cdf8d26
 F src/parse.y 023720cb8c3bef74e51738bca78335d0dc6d2cfd
 F src/pragma.c f9c157b0591419d2d3407dac90222020d2a6d822
 F src/printf.c 8c58b7b6d4069eec6ebe2d46bdbc3a89a367bf95
@@ -49,17 +49,17 @@ F src/random.c 775913e0b7fbd6295d21f12a7bd35b46387c44b2
 F src/select.c 3833e2b64cc6d249385ee44e13bf49c9ae5b903d
 F src/shell.c 920af040d3a33ea8919c82cee45b424ad841cee0
 F src/sqlite.h.in 35bec264dfb4965bbfeb7e75221f8658f210c30d
-F src/sqliteInt.h 235ce244b62bb26cc9ab394fb7a0724dd4e65c83
+F src/sqliteInt.h 36c649d7f2ab0affdc44e51c681dd1d5723ee1e9
 F src/table.c d845cb101b5afc1f7fea083c99e3d2fa7998d895
-F src/tclsqlite.c 819d92d305756c4ea57de023c387d2fa8a256aff
+F src/tclsqlite.c e816201db3ea6ba857a0351547be1d4b7286e95d
 F src/test1.c 9aa62b89d420e6763b5e7ae89a47f6cf87370477
-F src/test2.c 75819b0f2c63c6a0fd6995445881f2eb94036996
+F src/test2.c 9d611c45e1b07039a2bd95f5ea73178362b23229
 F src/test3.c 30985ebdfaf3ee1462a9b0652d3efbdc8d9798f5
 F src/test4.c 6e3e31acfaf21d66420fc35fda5b17dc0000cc8d
 F src/tokenize.c 6676b946fd8825b67ab52140af4fdc57a70bda48
 F src/trigger.c a9927b57c865b6f3df3fb5e40c9824d722660ded
 F src/update.c 4c50328ebc127852bde8e2950eb8933234802c21
-F src/util.c 122bc174f6c8c2eb6a9127d9f13c4c74f83b85e4
+F src/util.c b2287b07ddf55ef7aaa8888a9473123995a69f40
 F src/vacuum.c a4e8464c9f6d60659c5343e9d62c742463227820
 F src/vdbe.c 7c33f761fdc799633468766fb53eda4301daa6b3
 F src/vdbe.h ac987945e4dd6f987bca534c6005899f089fc270
@@ -114,7 +114,7 @@ F test/misc3.test 3b5e369514a3ba3f919fb7eafa7d027440b5079e
 F test/misuse.test 1095f26d1aed406c65e1d2eba651c4bb7c38cbff
 F test/notnull.test 7a08117a71e74b0321aaa937dbeb41a09d6eb1d0
 F test/null.test c14d0f4739f21e929b8115b72bf0c765b6bb1721
-F test/pager.test 331519008889d45f6df6697395e5bce6ee602fd9
+F test/pager.test 548968643d91c1c43a3a3eb1a232e9ca87b4069e
 F test/pragma.test 24a3f7a697b45cb90d664ebce5566bec7ac41571
 F test/printf.test 46b3d07d59d871d0831b4a657f6dfcafe0574850
 F test/progress.test 701b6115c2613128ececdfe1398a1bd0e1a4cfb3 x
@@ -133,7 +133,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 2f1d43df1311c9dc06acaa7a82e87bfea85dea5f
+F test/tester.tcl 5b47e21f442fe8afae963bc45beb54795cf5d162
 F test/thread1.test 53f050d5be6932d9430df7756edd379366508ff6
 F test/threadtest1.c f7f896e62ed46feae1dc411114a48c15a0f82ee2
 F test/threadtest2.c d94ca4114fd1504f7e0ae724bcd83d4b40931d86
@@ -188,7 +188,7 @@ F www/sqlite.tcl 3c83b08cf9f18aa2d69453ff441a36c40e431604
 F www/tclsqlite.tcl b9271d44dcf147a93c98f8ecf28c927307abd6da
 F www/vdbe.tcl 9b9095d4495f37697fd1935d10e14c6015e80aa1
 F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4
-P 818bdba5dc25cda56716fdda1781a3d4ecb3a111
-R f443d88ceb0074719c3a2c8d82169104
+P ce0bbd3a7159e12c86c5cde6571d6668b234827b
+R e6250126bdd2ced9348d9f2d5069495a
 U drh
-Z 85059b1060ba6075105dfb1d0e91a8dd
+Z 07ad078caa4fedefbf47bb778c51fa1e
index 9199c8c24fa343f27bb6075a058c66cd24c97dc5..067e908d3863226ed89f12ca2936837d9c4b941c 100644 (file)
@@ -1 +1 @@
-ce0bbd3a7159e12c86c5cde6571d6668b234827b
\ No newline at end of file
+910067a200c4b25b5d813a84146673d3d1c80952
\ No newline at end of file
index 6793f25b3630adb53d0707600d99ec5913e3537f..abccfb851b23bc73ac5e71bf78444a198ea30a88 100644 (file)
@@ -9,7 +9,7 @@
 **    May you share freely, never taking more than you give.
 **
 *************************************************************************
-** $Id: btree.c,v 1.104 2004/04/23 23:43:10 drh Exp $
+** $Id: btree.c,v 1.105 2004/04/26 14:10:21 drh Exp $
 **
 ** This file implements a external (disk-based) database using BTrees.
 ** For a detailed discussion of BTrees, refer to
 **
 **    SIZE    DESCRIPTION
 **      2     Byte offset of the next cell.  0 if this is the last cell
-**      4     Page number of the left child.  Omitted if leaf flag is set.
-**     var    Number of bytes of data.  Omitted if the zerodata flag is set.
-**     var    Number of bytes of key.  Omitted if the intkey flag is set.
+**      4     Page number of the left child. Omitted if leaf flag is set.
+**     var    Number of bytes of data. Omitted if the zerodata flag is set.
+**     var    Number of bytes of key. Or the key itself if intkey flag is set.
 **      *     Payload
 **      4     First page of the overflow chain.  Omitted if no overflow
 **
 #include <assert.h>
 
 /* Forward declarations */
-static BtOps sqliteBtreeOps;
-static BtCursorOps sqliteBtreeCursorOps;
+typedef struct MemPage MemPage;
 
 /*
 ** This is a magic string that appears at the beginning of every
@@ -181,17 +180,18 @@ static const char zMagicHeader[] = "SQLite version 3";
 ** The pageDestructor() routine handles that chore.
 */
 struct MemPage {
-  struct BTree *pBt;             /* Pointer back to BTree structure */
+  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 */
   u8 idxShift;                   /* True if Cell indices have changed */
-  u8 isOverfull;                 /* Some aCell[] points outside u.aDisk[] */
+  u8 isOverfull;                 /* Some aCell[] do not fit on page */
   u8 intKey;                     /* True if intkey flag is set */
   u8 leaf;                       /* True if leaf flag is set */
   u8 zeroData;                   /* True if zero data flag is set */
   u8 hdrOffset;                  /* 100 for page 1.  0 otherwise */
   Pgno pgno;                     /* Page number for this page */
   MemPage *pParent;              /* The parent of this page.  NULL for root */
-  int idxParent;                 /* Index in pParent->apCell[] of this node */
+  int idxParent;                 /* Index in pParent->aCell[] of this node */
   int nFree;                     /* Number of free bytes on the page */
   int nCell;                     /* Number of entries on this page */
   unsigned char **aCell;         /* Pointer to start of each cell */
@@ -202,18 +202,17 @@ struct MemPage {
 ** to the end.  EXTRA_SIZE is the number of bytes of space needed to hold
 ** that extra information.
 */
-#define EXTRA_SIZE sizeof(Mempage)
+#define EXTRA_SIZE sizeof(MemPage)
 
 /*
 ** Everything we need to know about an open database
 */
 struct Btree {
-  BtOps *pOps;          /* Function table */
   Pager *pPager;        /* The page cache */
   BtCursor *pCursor;    /* A list of all open cursors */
-  MemPage *page1;       /* First page of the database */
+  MemPage *pPage1;      /* First page of the database */
   u8 inTrans;           /* True if a transaction is in progress */
-  u8 inCkpt;            /* True if there is a checkpoint on the transaction */
+  u8 inStmt;            /* True if there is a checkpoint on the transaction */
   u8 readOnly;          /* True if the underlying file is readonly */
   int pageSize;         /* Number of usable bytes on each page */
   int maxLocal;         /* Maximum local payload */
@@ -226,13 +225,14 @@ typedef Btree Bt;
 ** MemPage.apCell[] of the entry.
 */
 struct BtCursor {
-  BtCursorOps *pOps;        /* Function table */
   Btree *pBt;               /* The Btree to which this cursor belongs */
   BtCursor *pNext, *pPrev;  /* Forms a linked list of all cursors */
   BtCursor *pShared;        /* Loop of cursors with the same root page */
+  int (*xCompare)(void*,int,const void*,int,const void*); /* Key comp func */
+  void *pArg;               /* First arg to xCompare() */
   Pgno pgnoRoot;            /* The root page of this tree */
   MemPage *pPage;           /* Page that contains the entry */
-  int idx;                  /* Index of the entry in pPage->apCell[] */
+  int idx;                  /* Index of the entry in pPage->aCell[] */
   u8 wrFlag;                /* True if writable */
   u8 eSkip;                 /* Determines if next step operation is a no-op */
   u8 iMatch;                /* compare result from last sqliteBtreeMoveto() */
@@ -246,11 +246,8 @@ struct BtCursor {
 #define SKIP_PREV     2   /* The next sqliteBtreePrevious() is a no-op */
 #define SKIP_INVALID  3   /* Calls to Next() and Previous() are invalid */
 
-/* Forward declarations */
-static int fileBtreeCloseCursor(BtCursor *pCur);
-
 /*
-** Read or write a two-, four-, and eight-byte integer values
+** Read or write a two-, four-, and eight-byte big-endian integer values.
 */
 static u32 get2byte(unsigned char *p){
   return (p[0]<<8) | p[1];
@@ -258,7 +255,7 @@ static u32 get2byte(unsigned char *p){
 static u32 get4byte(unsigned char *p){
   return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];
 }
-static u64 get4byte(unsigned char *p){
+static u64 get8byte(unsigned char *p){
   u64 v = get4byte(p);
   return (v<<32) | get4byte(&p[4]);
 }
@@ -306,34 +303,49 @@ static unsigned int putVarint(unsigned char *p, u64 v){
 }
 
 /*
-** Compute the total number of bytes that a Cell needs on the main
-** database page.  The number returned includes the Cell header,
-** local payload storage, and the pointer to overflow pages (if
-** applicable).  Additional space allocated on overflow pages
-** is NOT included in the value returned from this routine.
+** Parse a cell header and fill in the CellInfo structure.
 */
-static int cellSize(MemPage *pPage, unsigned char *pCell){
-  int n, nPayload;
-  u64 nData, nKey;
-  int maxPayload;
+static void parseCellHeader(
+  MemPage *pPage,         /* Page containing the cell */
+  unsigned char *pCell,   /* The cell */
+  u64 *pnData,            /* Number of bytes of data in payload */
+  u64 *pnKey,             /* Number of bytes of key, or key value for intKey */
+  int *pnHeader           /* Size of header in bytes.  Offset to payload */
+){
+  int n;
   if( pPage->leaf ){
     n = 2;
   }else{
     n = 6;
   }
   if( pPage->zeroData ){
-    nData = 0;
+    *pnData = 0;
   }else{
-    n += getVarint(&pCell[n], &nData);
+    n += getVarint(&pCell[n], pnData);
   }
-  if( pPage->intKey ){
-    u64 dummy;
-    nKey = getVarint(&pCell[n], &dummy);
-  }else{
-    n += getVarint(pCell, &nKey);
+  n += getVarint(pCell, pnKey);
+  *pnHeader = n;
+}
+
+/*
+** Compute the total number of bytes that a Cell needs on the main
+** database page.  The number returned includes the Cell header,
+** local payload storage, and the pointer to overflow pages (if
+** applicable).  Additional space allocated on overflow pages
+** is NOT included in the value returned from this routine.
+*/
+static int cellSize(MemPage *pPage, unsigned char *pCell){
+  CellInfo info;
+  int n;
+  u64 nData, nKey;
+  int nPayload, maxPayload;
+
+  parseCellHeader(pPage, pCell, &nData, &nKey, &n);
+  nPayload = (int)nData;
+  if( !pPage->intKey ){
+    nPayload += (int)nKey;
   }
-  nPayload = nKey + nData;
-  maxPayload = pPage->pBt->maxPayload;
+  maxPayload = pPage->pBt->maxLocal;
   if( nPayload>maxPayload ){
     nPayload = maxPayload + 4;
   }
@@ -346,8 +358,8 @@ static int cellSize(MemPage *pPage, unsigned char *pCell){
 ** into one big FreeBlk at the end of the page.
 */
 static void defragmentPage(MemPage *pPage){
-  int pc, i, n;
-  int start, hdr;
+  int pc, i, n, addr;
+  int start, hdr, size;
   int leftover;
   unsigned char *oldPage;
   unsigned char newPage[SQLITE_PAGE_SIZE];
@@ -357,31 +369,31 @@ static void defragmentPage(MemPage *pPage){
   assert( pPage->pageSize <= SQLITE_PAGE_SIZE );
   oldPage = pPage->aData;
   hdr = pPage->hdrOffset;
-  ptr = 3+hdr;
+  addr = 3+hdr;
   n = 6+hdr;
   if( !pPage->leaf ){
     n += 4;
   }
   start = n;
-  pc = get2byte(&oldPage[ptr]);
+  pc = get2byte(&oldPage[addr]);
   i = 0;
   while( pc>0 ){
-    assert( n<pPage->pageSize );
+    assert( n<pPage->pBt->pageSize );
     size = cellSize(pPage, &oldPage[pc]);
     memcpy(&newPage[n], &oldPage[pc], size);
-    put2byte(&newPage[ptr],n);
+    put2byte(&newPage[addr],n);
     pPage->aCell[i] = &oldPage[n];
     n += size;
-    ptr = pc;
+    addr = pc;
     pc = get2byte(&oldPage[pc]);
   }
-  leftover = pPage->pageSize - n;
+  leftover = pPage->pBt->pageSize - n;
   assert( leftover>=0 );
   assert( pPage->nFree==leftover );
   if( leftover<4 ){
     oldPage[hdr+5] = leftover;
     leftover = 0;
-    n = pPage->pageSize;
+    n = pPage->pBt->pageSize;
   }
   memcpy(&oldPage[start], &newPage[start], n-start);
   if( leftover==0 ){
@@ -411,7 +423,7 @@ static void defragmentPage(MemPage *pPage){
 ** nByte in size or that larger.
 */
 static int allocateSpace(MemPage *pPage, int nByte){
-  int ptr, pc, hdr;
+  int addr, pc, hdr;
   int size;
   unsigned char *data;
 #ifndef NDEBUG
@@ -427,31 +439,31 @@ static int allocateSpace(MemPage *pPage, int nByte){
   if( data[hdr+5]>=252 ){
     defragmentPage(pPage);
   }
-  ptr = hdr+1;
-  pc = get2byte(&data[ptr]);
-  assert( ptr<pc );
+  addr = hdr+1;
+  pc = get2byte(&data[addr]);
+  assert( addr<pc );
   assert( pc<=pPage->pageSize-4 );
-  while( (size = get2byte(&data[pc+2])<nByte ){
-    ptr = pc;
-    pc = get2byte(&data[ptr]);
+  while( (size = get2byte(&data[pc+2]))<nByte ){
+    addr = pc;
+    pc = get2byte(&data[addr]);
     assert( pc<=pPage->pageSize-4 );
-    assert( pc>=ptr+size+4 || pc==0 );
+    assert( pc>=addr+size+4 || pc==0 );
     if( pc==0 ){
       assert( (cnt++)==0 );
       defragmentPage(pPage);
       assert( data[hdr+5]==0 );
-      ptr = pPage->hdrOffset+1;
-      pc = get2byte(&data[ptr]);
+      addr = pPage->hdrOffset+1;
+      pc = get2byte(&data[addr]);
     }
   }
   assert( pc>0 && size>=nByte );
   assert( pc+size<=pPage->pageSize );
   if( size>nByte+4 ){
-    put2byte(&data[ptr], pc+nByte);
+    put2byte(&data[addr], pc+nByte);
     put2byte(&data[pc+size], get2byte(&data[pc]));
     put2byte(&data[pc+size+2], size-nByte);
   }else{
-    put2byte(&data[ptr], get2byte(&data[pc]));
+    put2byte(&data[addr], get2byte(&data[pc]));
     data[hdr+5] += size-nByte;
   }
   pPage->nFree -= nByte;
@@ -469,7 +481,7 @@ static int allocateSpace(MemPage *pPage, int nByte){
 */
 static void freeSpace(MemPage *pPage, int start, int size){
   int end = start + size;  /* End of the segment being freed */
-  int ptr, pbegin, pend;
+  int addr, pbegin, pend;
 #ifndef NDEBUG
   int tsize = 0;          /* Total size of all freeblocks */
 #endif
@@ -482,24 +494,24 @@ static void freeSpace(MemPage *pPage, int start, int size){
   if( size<4 ) size = 4;
 
   /* Add the space back into the linked list of freeblocks */
-  ptr = pPage->hdrOffset + 1;
-  while( (pbegin = get2byte(&data[ptr]))<start && pbegin>0 ){
+  addr = pPage->hdrOffset + 1;
+  while( (pbegin = get2byte(&data[addr]))<start && pbegin>0 ){
     assert( pbegin<=pPage->pBt->pageSize-4 );
-    assert( pbegin>ptr );
-    ptr = pbegin;
+    assert( pbegin>addr );
+    addr = pbegin;
   }
   assert( pbegin<=pPage->pBt->pageSize-4 );
-  assert( pbegin>ptr || pbegin==0 );
-  put2bytes(&data[ptr], start);
+  assert( pbegin>addr || pbegin==0 );
+  put2bytes(&data[addr], start);
   put2bytes(&data[start], pbegin);
   put2bytes(&data[start+2], size);
   pPage->nFree += size;
 
   /* Coalesce adjacent free blocks */
-  ptr = pPage->hdrOffset + 1;
-  while( (pbegin = get2byte(&data[ptr]))>0 ){
+  addr = pPage->hdrOffset + 1;
+  while( (pbegin = get2byte(&data[addr]))>0 ){
     int pnext, psize;
-    assert( pbegin>ptr );
+    assert( pbegin>addr );
     assert( pbegin<pPage->pBt->pageSize-4 );
     pnext = get2byte(&data[pbegin]);
     psize = get2byte(&data[pbegin+2]);
@@ -511,12 +523,13 @@ static void freeSpace(MemPage *pPage, int start, int size){
       put2byte(&data[pbegin+2], pnext+get2byte(&data[pnext+2])-pbegin);
     }else{
       assert( (tsize += psize)>0 );
-      ptr = pbegin;
+      addr = pbegin;
     }
   }
   assert( tsize+data[pPage->hdrOffset+5]==pPage->nFree );
 }
 
+#if 0
 /*
 ** The following is the default comparison function for (non-integer)
 ** keys in the btrees.  This function returns negative, zero, or
@@ -586,7 +599,7 @@ static int keyComp(
 bad_key:
   return 1;
 }
-  
+#endif
 
 /*
 ** Initialize the auxiliary information for a disk block.
@@ -602,17 +615,14 @@ bad_key:
 ** we failed to detect any corruption.
 */
 static int initPage(
-  Bt *pBt,               /* The Btree */
-  unsigned char *data,   /* Start of the data for the page */
-  Pgno pgnoThis,         /* The page number */
+  MemPage *pPage,        /* The page to be initialized */
   MemPage *pParent       /* The parent.  Might be NULL */
 ){
-  MemPage *pPage;
-  int c, pc, i;
+  int c, pc, i, hdr;
   int sumCell = 0;       /* Total size of all cells */
-  unsigned char *data;
 
-  pPage = (MemPage*)&aData[pBt->pageSize];
+  assert( pPage->pBt!=0 );
+  assert( pPage->aData == &((unsigned char*)pPage)[pPage->pBt->pageSize] );
   if( pPage->pParent ){
     assert( pPage->pParent==pParent );
     return SQLITE_OK;
@@ -621,12 +631,11 @@ static int initPage(
     pPage->pParent = pParent;
     sqlitepager_ref(pParent->aData);
   }
-  if( pPage->pBt!=0 ) return SQLITE_OK;
-  pPage->pBt = pBt;
+  if( pPage->isInit ) return SQLITE_OK;
   pPage->nCell = 0;
-  pPage->pgno = pgnoThis;
+  assert( sqlitepager_pagenumber(pPage->aData)==pPage->pgno );
   pPage->hdrOffset = hdr = pgnoThis==1 ? 100 : 0;
-  c = data[pPage->hdrOffset];
+  c = pPage->aData[pPage->hdrOffset];
   pPage->intKey = (c & PTF_INTKEY)!=0;
   pPage->zeroData = (c & PTF_ZERODATA)!=0;
   pPage->leaf = (c & PTF_INTKEY)!=0;
@@ -658,7 +667,7 @@ static int initPage(
     if( pc>=pBt->pageSize ) return SQLITE_CORRUPT;
     next = get2byte(&data[pc]);
     size = get2byte(&data[pc+2]);
-    if( next>0 && next<=pc+size+3 ) return SQLITE_CURRUPT;
+    if( next>0 && next<=pc+size+3 ) return SQLITE_CORRUPT;
     pPage->nFree += size;
     pc = next;
   }
@@ -680,7 +689,7 @@ static int initPage(
 static void zeroPage(MemPage *pPage, int flags){
   unsigned char *data = pPage->aData;
   Btree *pBt = pPage->pBt;
-  int hdr = pPage->pgno==1 ? 100 : 0;
+  int hdr = pPage->hdrOffset;
   int first;
 
   assert( sqlitepager_iswriteable(data) );
@@ -699,6 +708,37 @@ static void zeroPage(MemPage *pPage, int flags){
   pPage->hdrOffset = hdr;
 }
 
+/*
+** Get a page from the pager.  Initialize the MemPage.pBt and
+** MemPage.aData elements if needed.
+*/
+static int getPage(Btree *pBt, Pgno pgno, MemPage **ppPage){
+  int rc;
+  unsigned char *aData;
+  MemPage *pPage;
+  rc = sqlitepager_get(pBt->pPager, pgno, &aData);
+  if( rc ) return rc;
+  pPage = (MemPage*)aData[pBt->pageSize];
+  pPage->aData = aData;
+  pPage->pBt = pBt;
+  pPage->pgno = pgno;
+  *ppPage = pPage;
+  return SQLITE_OK;
+}
+
+/*
+** Release a MemPage.  This should be called once for each prior
+** call to getPage.
+*/
+static int releasePage(MemPage *pPage){
+  if( pPage ){
+    assert( pPage->aData );
+    assert( pPage->pBt );
+    assert( &pPage->aData[pPage->pBt->pageSize]==(unsigned char*)pPage );
+    sqlitepager_unref(pPage->aData);
+  }
+}
+
 /*
 ** This routine is called when the reference count for a page
 ** reaches zero.  We need to unref the pParent pointer when that
@@ -709,10 +749,11 @@ static void pageDestructor(void *pData){
   if( pPage->pParent ){
     MemPage *pParent = pPage->pParent;
     pPage->pParent = 0;
-    sqlitepager_unref(pParent->aData);
+    releasepage(pParent);
   }
   sqliteFree(pPage->aCell);
   pPage->aCell = 0;
+  pPage->isInit = 0;
 }
 
 /*
@@ -727,13 +768,15 @@ static void pageDestructor(void *pData){
 ** database file will be deleted when sqliteBtreeClose() is called.
 */
 int sqliteBtreeOpen(
-  const char *zFilename,    /* Name of the file containing the BTree database */
-  int omitJournal,          /* if TRUE then do not journal this file */
-  int nCache,               /* How many pages in the page cache */
-  Btree **ppBtree           /* Pointer to new Btree object written here */
+  const char *zFilename,  /* Name of the file containing the BTree database */
+  Btree **ppBtree,        /* Pointer to new Btree object written here */
+  int nCache,             /* Number of cache pages */
+  int flags               /* Options */
 ){
   Btree *pBt;
-  int rc;
+  int rc, i;
+  int nCache = 2000;
+  int omitJournal = 0;
 
   /*
   ** The following asserts make sure that structures used by the btree are
@@ -754,7 +797,7 @@ int sqliteBtreeOpen(
   }
   if( nCache<10 ) nCache = 10;
   rc = sqlitepager_open(&pBt->pPager, zFilename, nCache, EXTRA_SIZE,
-                        !omitJournal);
+                        (flags & BTREE_OMIT_JOURNAL)==0);
   if( rc!=SQLITE_OK ){
     if( pBt->pPager ) sqlitepager_close(pBt->pPager);
     sqliteFree(pBt);
@@ -765,7 +808,6 @@ int sqliteBtreeOpen(
   pBt->pCursor = 0;
   pBt->page1 = 0;
   pBt->readOnly = sqlitepager_isreadonly(pBt->pPager);
-  pBt->pOps = &sqliteBtreeOps;
   pBt->pageSize = SQLITE_PAGE_SIZE;
   pBt->maxLocal = (SQLITE_PAGE_SIZE-10)/4-12;
   *ppBtree = pBt;
@@ -775,9 +817,9 @@ int sqliteBtreeOpen(
 /*
 ** Close an open database and invalidate all cursors.
 */
-static int fileBtreeClose(Btree *pBt){
+int sqlite3BtreeClose(Btree *pBt){
   while( pBt->pCursor ){
-    fileBtreeCloseCursor(pBt->pCursor);
+    sqlite3BtreeCloseCursor(pBt->pCursor);
   }
   sqlitepager_close(pBt->pPager);
   sqliteFree(pBt);
@@ -799,7 +841,7 @@ static int fileBtreeClose(Btree *pBt){
 ** Synchronous is on by default so database corruption is not
 ** normally a worry.
 */
-static int fileBtreeSetCacheSize(Btree *pBt, int mxPage){
+int sqilte3BtreeSetCacheSize(Btree *pBt, int mxPage){
   sqlitepager_set_cachesize(pBt->pPager, mxPage);
   return SQLITE_OK;
 }
@@ -812,7 +854,7 @@ static int fileBtreeSetCacheSize(Btree *pBt, int mxPage){
 ** is a very low but non-zero probability of damage.  Level 3 reduces the
 ** probability of damage to near zero but with a write performance reduction.
 */
-static int fileBtreeSetSafetyLevel(Btree *pBt, int level){
+int sqlite3BtreeSetSafetyLevel(Btree *pBt, int level){
   sqlitepager_set_safety_level(pBt->pPager, level);
   return SQLITE_OK;
 }
@@ -829,27 +871,28 @@ static int fileBtreeSetSafetyLevel(Btree *pBt, int level){
 */
 static int lockBtree(Btree *pBt){
   int rc;
-  unsigned char *data;
+  MemPage *pPage1;
   if( pBt->page1 ) return SQLITE_OK;
-  rc = sqlitepager_get(pBt->pPager, 1, (void**)&data);
+  rc = getPage(pBt, 1, &pPage1);
   if( rc!=SQLITE_OK ) return rc;
+  
 
   /* Do some checking to help insure the file we opened really is
   ** a valid database file. 
   */
   if( sqlitepager_pagecount(pBt->pPager)>0 ){
-    if( memcmp(data, zMagicHeader, 16)!=0 ){
+    if( memcmp(pPage1->aData, zMagicHeader, 16)!=0 ){
       rc = SQLITE_NOTADB;
       goto page1_init_failed;
     }
     /*** TBD:  Other header checks such as page size ****/
   }
-  pBt->page1 = (MemPage*)&data[SQLITE_PAGE_SIZE];
+  pBt->pPage1 = pPage1;
   return rc;
 
 page1_init_failed:
-  sqlitepager_unref(pBt->data);
-  pBt->page1 = 0;
+  releasePage(pPage1);
+  pBt->pPage1 = 0;
   return rc;
 }
 
@@ -864,11 +907,11 @@ page1_init_failed:
 ** If there is a transaction in progress, this routine is a no-op.
 */
 static void unlockBtreeIfUnused(Btree *pBt){
-  if( pBt->inTrans==0 && pBt->pCursor==0 && pBt->page1!=0 ){
-    sqlitepager_unref(pBt->page1->aData);
-    pBt->page1 = 0;
+  if( pBt->inTrans==0 && pBt->pCursor==0 && pBt->pPage1!=0 ){
+    releasePage(pBt->pPage1);
+    pBt->pPage1 = 0;
     pBt->inTrans = 0;
-    pBt->inCkpt = 0;
+    pBt->inStmt = 0;
   }
 }
 
@@ -881,7 +924,7 @@ static int newDatabase(Btree *pBt){
   unsigned char *data;
   int rc;
   if( sqlitepager_pagecount(pBt->pPager)>1 ) return SQLITE_OK;
-  pP1 = pBt->page1;
+  pP1 = pBt->pPage1;
   assert( pP1!=0 );
   data = pP1->aData;
   rc = sqlitepager_write(data);
@@ -911,23 +954,23 @@ static int newDatabase(Btree *pBt){
 **      sqliteBtreeDelete()
 **      sqliteBtreeUpdateMeta()
 */
-static int fileBtreeBeginTrans(Btree *pBt){
+int sqlite3BtreeBeginTrans(Btree *pBt){
   int rc;
   if( pBt->inTrans ) return SQLITE_ERROR;
   if( pBt->readOnly ) return SQLITE_READONLY;
-  if( pBt->page1==0 ){
+  if( pBt->pPage1==0 ){
     rc = lockBtree(pBt);
     if( rc!=SQLITE_OK ){
       return rc;
     }
   }
-  rc = sqlitepager_begin(pBt->page1);
+  rc = sqlitepager_begin(pBt->pPage1->aData);
   if( rc==SQLITE_OK ){
     rc = newDatabase(pBt);
   }
   if( rc==SQLITE_OK ){
     pBt->inTrans = 1;
-    pBt->inCkpt = 0;
+    pBt->inStmt = 0;
   }else{
     unlockBtreeIfUnused(pBt);
   }
@@ -940,11 +983,11 @@ static int fileBtreeBeginTrans(Btree *pBt){
 ** This will release the write lock on the database file.  If there
 ** are no active cursors, it also releases the read lock.
 */
-static int fileBtreeCommit(Btree *pBt){
+int sqlite3BtreeCommit(Btree *pBt){
   int rc;
   rc = pBt->readOnly ? SQLITE_OK : sqlitepager_commit(pBt->pPager);
   pBt->inTrans = 0;
-  pBt->inCkpt = 0;
+  pBt->inStmt = 0;
   unlockBtreeIfUnused(pBt);
   return rc;
 }
@@ -958,16 +1001,17 @@ static int fileBtreeCommit(Btree *pBt){
 ** This will release the write lock on the database file.  If there
 ** are no active cursors, it also releases the read lock.
 */
-static int fileBtreeRollback(Btree *pBt){
+int sqlite3BtreeRollback(Btree *pBt){
   int rc;
   BtCursor *pCur;
   if( pBt->inTrans==0 ) return SQLITE_OK;
   pBt->inTrans = 0;
-  pBt->inCkpt = 0;
+  pBt->inStmt = 0;
   rc = pBt->readOnly ? SQLITE_OK : sqlitepager_rollback(pBt->pPager);
   for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){
-    if( pCur->pPage && pCur->pPage->pBt==0 ){
-      sqlitepager_unref(pCur->pPage);
+    MemPage *pPage = pCur->pPage;
+    if( pPage && !pPage->isInit ){
+      releasePage(pPage);
       pCur->pPage = 0;
     }
   }
@@ -985,13 +1029,13 @@ static int fileBtreeRollback(Btree *pBt){
 ** Only one checkpoint may be active at a time.  It is an error to try
 ** to start a new checkpoint if another checkpoint is already active.
 */
-static int fileBtreeBeginCkpt(Btree *pBt){
+int sqlite3BtreeBeginStmt(Btree *pBt){
   int rc;
-  if( !pBt->inTrans || pBt->inCkpt ){
+  if( !pBt->inTrans || pBt->inStmt ){
     return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR;
   }
   rc = pBt->readOnly ? SQLITE_OK : sqlitepager_ckpt_begin(pBt->pPager);
-  pBt->inCkpt = 1;
+  pBt->inStmt = 1;
   return rc;
 }
 
@@ -1000,14 +1044,14 @@ static int fileBtreeBeginCkpt(Btree *pBt){
 ** Commit a checkpoint to transaction currently in progress.  If no
 ** checkpoint is active, this is a no-op.
 */
-static int fileBtreeCommitCkpt(Btree *pBt){
+int sqlite3BtreeCommitStmt(Btree *pBt){
   int rc;
-  if( pBt->inCkpt && !pBt->readOnly ){
+  if( pBt->inStmt && !pBt->readOnly ){
     rc = sqlitepager_ckpt_commit(pBt->pPager);
   }else{
     rc = SQLITE_OK;
   }
-  pBt->inCkpt = 0;
+  pBt->inStmt = 0;
   return rc;
 }
 
@@ -1019,21 +1063,39 @@ static int fileBtreeCommitCkpt(Btree *pBt){
 ** to use a cursor that was open at the beginning of this operation
 ** will result in an error.
 */
-static int fileBtreeRollbackCkpt(Btree *pBt){
+int sqlite3BtreeRollbackStmt(Btree *pBt){
   int rc;
   BtCursor *pCur;
-  if( pBt->inCkpt==0 || pBt->readOnly ) return SQLITE_OK;
+  if( pBt->inStmt==0 || pBt->readOnly ) return SQLITE_OK;
   rc = sqlitepager_ckpt_rollback(pBt->pPager);
   for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){
-    if( pCur->pPage && pCur->pPage->isInit==0 ){
-      sqlitepager_unref(pCur->pPage);
+    MemPage *pPage = pCur->pPage;
+    if( pPage && !pPage->isInit ){
+      releasePage(pPage);
       pCur->pPage = 0;
     }
   }
-  pBt->inCkpt = 0;
+  pBt->inStmt = 0;
   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 
@@ -1069,9 +1131,21 @@ static int fileBtreeRollbackCkpt(Btree *pBt){
 ** 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.
-*/
-static 
-int fileBtreeCursor(Btree *pBt, int iTable, int wrFlag, BtCursor **ppCur){
+**
+** 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.
+*/
+int sqlite3BtreeCursor(
+  Btree *pBt,                                 /* 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 */
+){
   int rc;
   BtCursor *pCur, *pRing;
 
@@ -1092,15 +1166,16 @@ int fileBtreeCursor(Btree *pBt, int iTable, int wrFlag, BtCursor **ppCur){
     goto create_cursor_exception;
   }
   pCur->pgnoRoot = (Pgno)iTable;
-  rc = sqlitepager_get(pBt->pPager, pCur->pgnoRoot, (void**)&pCur->pPage);
+  rc = getPage(pBt, pCur->pgnoRoot, (void**)&pCur->pPage);
   if( rc!=SQLITE_OK ){
     goto create_cursor_exception;
   }
-  rc = initPage(pBt, pCur->pPage, pCur->pgnoRoot, 0);
+  rc = initPage(pCur->pPage, 0);
   if( rc!=SQLITE_OK ){
     goto create_cursor_exception;
   }
-  pCur->pOps = &sqliteBtreeCursorOps;
+  pCur->xCompare = xCmp ? xCmp : dfltCompare;
+  pCur->pArg = pArg;
   pCur->pBt = pBt;
   pCur->wrFlag = wrFlag;
   pCur->idx = 0;
@@ -1125,7 +1200,7 @@ int fileBtreeCursor(Btree *pBt, int iTable, int wrFlag, BtCursor **ppCur){
 create_cursor_exception:
   *ppCur = 0;
   if( pCur ){
-    if( pCur->pPage ) sqlitepager_unref(pCur->pPage);
+    releasePage(pCur->pPage);
     sqliteFree(pCur);
   }
   unlockBtreeIfUnused(pBt);
@@ -1136,7 +1211,7 @@ create_cursor_exception:
 ** Close a cursor.  The read lock on the database file is released
 ** when the last cursor is closed.
 */
-static int fileBtreeCloseCursor(BtCursor *pCur){
+int sqlite3BtreeCloseCursor(BtCursor *pCur){
   Btree *pBt = pCur->pBt;
   if( pCur->pPrev ){
     pCur->pPrev->pNext = pCur->pNext;
@@ -1146,9 +1221,7 @@ static int fileBtreeCloseCursor(BtCursor *pCur){
   if( pCur->pNext ){
     pCur->pNext->pPrev = pCur->pPrev;
   }
-  if( pCur->pPage ){
-    sqlitepager_unref(pCur->pPage);
-  }
+  releasePage(pCur->pPage);
   if( pCur->pShared!=pCur ){
     BtCursor *pRing = pCur->pShared;
     while( pRing->pShared!=pCur ){ pRing = pRing->pShared; }
@@ -1168,7 +1241,7 @@ static void getTempCursor(BtCursor *pCur, BtCursor *pTempCur){
   pTempCur->pNext = 0;
   pTempCur->pPrev = 0;
   if( pTempCur->pPage ){
-    sqlitepager_ref(pTempCur->pPage);
+    sqlitepager_ref(pTempCur->pPage->aData);
   }
 }
 
@@ -1178,19 +1251,19 @@ static void getTempCursor(BtCursor *pCur, BtCursor *pTempCur){
 */
 static void releaseTempCursor(BtCursor *pCur){
   if( pCur->pPage ){
-    sqlitepager_unref(pCur->pPage);
+    sqlitepager_unref(pCur->pPage->aData);
   }
 }
 
 /*
-** Set *pSize to the number of bytes of key in the entry the
-** cursor currently points to.  Always return SQLITE_OK.
-** Failure is not possible.  If the cursor is not currently
-** pointing to an entry (which can happen, for example, if
-** the database is empty) then *pSize is set to 0.
+** Set *pSize to the size of the buffer needed to hold the value of
+** the key for the current entry.  If the cursor is not pointing
+** to a valid entry, *pSize is set to 0. 
+**
+** For a table with the intKey flag set, this routine returns the key
+** itself, not the number of bytes in the key.
 */
-static int fileBtreeKeySize(BtCursor *pCur, int *pSize){
-  Cell *pCell;
+int sqlite3BtreeKeySize(BtCursor *pCur, u64 *pSize){
   MemPage *pPage;
 
   pPage = pCur->pPage;
@@ -1198,8 +1271,15 @@ static int fileBtreeKeySize(BtCursor *pCur, int *pSize){
   if( pCur->idx >= pPage->nCell ){
     *pSize = 0;
   }else{
-    pCell = pPage->apCell[pCur->idx];
-    *pSize = NKEY(pCur->pBt, pCell->h);
+    unsigned char *cell = pPage->aCell[pCur->idx];
+    cell += 2;   /* Skip the offset to the next cell */
+    if( pPage->leaf ){
+      cell += 4;  /* Skip the child pointer */
+    }
+    if( !pPage->zeroData ){
+      while( (0x80&*(data++))!=0 ){}  /* Skip the data size number */
+    }
+    getVarint(data, pSize);
   }
   return SQLITE_OK;
 }
@@ -1212,18 +1292,51 @@ static int fileBtreeKeySize(BtCursor *pCur, int *pSize){
 ** This routine does not make a distinction between key and data.
 ** It just reads bytes from the payload area.
 */
-static int getPayload(BtCursor *pCur, int offset, int amt, char *zBuf){
-  char *aPayload;
+static int getPayload(
+  BtCursor *pCur,      /* Cursor pointing to entry to read from */
+  int offset,          /* Begin reading this far into payload */
+  int amt,             /* Read this many bytes */
+  unsigned char *pBuf, /* Write the bytes into this buffer */ 
+  int skipKey          /* offset begins at data if this is true */
+){
+  unsigned char *aPayload;
   Pgno nextPage;
   int rc;
-  Btree *pBt = pCur->pBt;
+  MemPage *pPage;
+  Btree *pBt;
+  u64 nData, nKey;
+  int maxLocal, ovflSize;
+
   assert( pCur!=0 && pCur->pPage!=0 );
-  assert( pCur->idx>=0 && pCur->idx<pCur->pPage->nCell );
-  aPayload = pCur->pPage->apCell[pCur->idx]->aPayload;
-  if( offset<MX_LOCAL_PAYLOAD ){
+  pBt = pCur->pBt;
+  pPage = pCur->pPage;
+  assert( pCur->idx>=0 && pCur->idx<pPage->nCell );
+  aPayload = pPage->aCell[pCur->idx];
+  aPayload += 2;  /* Skip the next cell index */
+  if( pPage->leaf ){
+    aPayload += 4;  /* Skip the child pointer */
+  }
+  if( pPage->zeroData ){
+    nData = 0;
+  }else{
+    aPayload += getVarint(aPayload, &nData);
+  }
+  aPayload += getVarInt(aPayload, &nKey);
+  if( pPage->intKey ){
+    nKey = 0;
+  }
+  assert( offset>=0 );
+  if( skipKey ){
+    offset += nKey;
+  }
+  if( offset+amt > nKey+nData ){
+    sqlite SQLITE_ERROR;
+  }
+  maxLocal = pBt->maxLocal
+  if( offset<maxLocal ){
     int a = amt;
-    if( a+offset>MX_LOCAL_PAYLOAD ){
-      a = MX_LOCAL_PAYLOAD - offset;
+    if( a+offset>maxLocal ){
+      a = maxLocal - offset;
     }
     memcpy(zBuf, &aPayload[offset], a);
     if( a==amt ){
@@ -1233,31 +1346,31 @@ static int getPayload(BtCursor *pCur, int offset, int amt, char *zBuf){
     zBuf += a;
     amt -= a;
   }else{
-    offset -= MX_LOCAL_PAYLOAD;
+    offset -= maxLocal;
   }
   if( amt>0 ){
-    nextPage = SWAB32(pBt, pCur->pPage->apCell[pCur->idx]->ovfl);
+    nextPage = get4bytes(&aPayload[maxLocal]);
   }
+  ovflSize = pBt->pageSize - 4;
   while( amt>0 && nextPage ){
-    OverflowPage *pOvfl;
-    rc = sqlitepager_get(pBt->pPager, nextPage, (void**)&pOvfl);
+    rc = sqlitepager_get(pBt->pPager, nextPage, (void**)&aPayload);
     if( rc!=0 ){
       return rc;
     }
-    nextPage = SWAB32(pBt, pOvfl->iNext);
-    if( offset<OVERFLOW_SIZE ){
+    nextPage = get4bytes(aPayload);
+    if( offset<ovflSize ){
       int a = amt;
-      if( a + offset > OVERFLOW_SIZE ){
-        a = OVERFLOW_SIZE - offset;
+      if( a + offset > ovflSize ){
+        a = ovflSize - offset;
       }
-      memcpy(zBuf, &pOvfl->aPayload[offset], a);
+      memcpy(zBuf, &aPayload[offset], a);
       offset = 0;
       amt -= a;
       zBuf += a;
     }else{
-      offset -= OVERFLOW_SIZE;
+      offset -= ovflSize;
     }
-    sqlitepager_unref(pOvfl);
+    sqlitepager_unref(aPayload);
   }
   if( amt>0 ){
     return SQLITE_CORRUPT;
@@ -1266,33 +1379,67 @@ static int getPayload(BtCursor *pCur, int offset, int amt, char *zBuf){
 }
 
 /*
-** Read part of the key associated with cursor pCur.  A maximum
-** of "amt" bytes will be transfered into zBuf[].  The transfer
-** begins at "offset".  The number of bytes actually read is
-** returned. 
+** Read part of the key associated with cursor pCur.  Exactly
+** "amt" bytes will be transfered into zBuf[].  The transfer
+** begins at "offset".
 **
-** Change:  It used to be that the amount returned will be smaller
-** than the amount requested if there are not enough bytes in the key
-** to satisfy the request.  But now, it must be the case that there
-** is enough data available to satisfy the request.  If not, an exception
-** is raised.  The change was made in an effort to boost performance
-** by eliminating unneeded tests.
+** Return SQLITE_OK on success or an error code if anything goes
+** wrong.  An error is returned if "offset+amt" is larger than
+** the available payload.
 */
-static int fileBtreeKey(BtCursor *pCur, int offset, int amt, char *zBuf){
+int sqlite3BtreeKey(BtCursor *pCur, int offset, int amt, void *pBuf){
   MemPage *pPage;
 
   assert( amt>=0 );
   assert( offset>=0 );
   assert( pCur->pPage!=0 );
   pPage = pCur->pPage;
-  if( pCur->idx >= pPage->nCell ){
+  if( pCur->idx >= pPage->nCell || pPage->intKey ){
+    assert( amt==0 );
+    return SQLITE_OK;
+  }
+  return getPayload(pCur, offset, amt, (unsigned char*)pBuf, 0);
+}
+
+/*
+** Return a pointer to the key of record that cursor pCur
+** is point to if the entire key is in contiguous memory.
+** If the key is split up among multiple tables, return 0.
+** If pCur is not pointing to a valid entry return 0.
+**
+** The pointer returned is ephemeral.  The key may move
+** or be destroyed on the next call to any Btree routine.
+**
+** This routine is used to do quick key comparisons in the
+** common case where the entire key fits in the payload area
+** of a cell and does not overflow onto secondary pages.
+*/
+void *sqlite3BtreeKeyFetch(BtCursor *pCur){
+  unsigned char *aPayload;
+  MemPage *pPage;
+  Btree *pBt;
+  u64 nData, nKey;
+
+  assert( pCur!=0 && pCur->pPage!=0 );
+  pBt = pCur->pBt;
+  pPage = pCur->pPage;
+  assert( pCur->idx>=0 && pCur->idx<pPage->nCell );
+  aPayload = pPage->aCell[pCur->idx];
+  aPayload += 2;  /* Skip the next cell index */
+  if( pPage->leaf ){
+    aPayload += 4;  /* Skip the child pointer */
+  }
+  if( !pPage->zeroData ){
+    aPayload += getVarint(aPayload, &nData);
+  }
+  aPayload += getVarInt(aPayload, &nKey);
+  if( pPage->intKey || nKey>pBt->maxLocal ){
     return 0;
   }
-  assert( amt+offset <= NKEY(pCur->pBt, pPage->apCell[pCur->idx]->h) );
-  getPayload(pCur, offset, amt, zBuf);
-  return amt;
+  return aPayload;
 }
 
+
 /*
 ** Set *pSize to the number of bytes of data in the entry the
 ** cursor currently points to.  Always return SQLITE_OK.
@@ -1300,31 +1447,38 @@ static int fileBtreeKey(BtCursor *pCur, int offset, int amt, char *zBuf){
 ** pointing to an entry (which can happen, for example, if
 ** the database is empty) then *pSize is set to 0.
 */
-static int fileBtreeDataSize(BtCursor *pCur, int *pSize){
-  Cell *pCell;
+int sqlite3BtreeDataSize(BtCursor *pCur, u32 *pSize){
   MemPage *pPage;
 
   pPage = pCur->pPage;
   assert( pPage!=0 );
-  if( pCur->idx >= pPage->nCell ){
+  if( pCur->idx >= pPage->nCell || pPage->zeroData ){
     *pSize = 0;
   }else{
-    pCell = pPage->apCell[pCur->idx];
-    *pSize = NDATA(pCur->pBt, pCell->h);
+    unsigned char *cell;
+    u64 size;
+    cell = pPage->aCell[pCur->idx];
+    cell += 2;   /* Skip the offset to the next cell */
+    if( pPage->leaf ){
+      cell += 4;  /* Skip the child pointer */
+    }
+    getVarint(data, size);
+    assert( (size & 0x00000000ffffffff)==size );
+    *pSize = size;
   }
   return SQLITE_OK;
 }
 
 /*
-** Read part of the data associated with cursor pCur.  A maximum
-** of "amt" bytes will be transfered into zBuf[].  The transfer
-** begins at "offset".  The number of bytes actually read is
-** returned.  The amount returned will be smaller than the
-** amount requested if there are not enough bytes in the data
-** to satisfy the request.
+** Read part of the data associated with cursor pCur.  Exactly
+** "amt" bytes will be transfered into zBuf[].  The transfer
+** begins at "offset".
+**
+** Return SQLITE_OK on success or an error code if anything goes
+** wrong.  An error is returned if "offset+amt" is larger than
+** the available payload.
 */
-static int fileBtreeData(BtCursor *pCur, int offset, int amt, char *zBuf){
-  Cell *pCell;
+int sqlite3BtreeData(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){
   MemPage *pPage;
 
   assert( amt>=0 );
@@ -1335,115 +1489,28 @@ static int fileBtreeData(BtCursor *pCur, int offset, int amt, char *zBuf){
     return 0;
   }
   pCell = pPage->apCell[pCur->idx];
-  assert( amt+offset <= NDATA(pCur->pBt, pCell->h) );
-  getPayload(pCur, offset + NKEY(pCur->pBt, pCell->h), amt, zBuf);
-  return amt;
-}
-
-/*
-** Compare an external key against the key on the entry that pCur points to.
-**
-** The external key is pKey and is nKey bytes long.  The last nIgnore bytes
-** of the key associated with pCur are ignored, as if they do not exist.
-** (The normal case is for nIgnore to be zero in which case the entire
-** internal key is used in the comparison.)
-**
-** The comparison result is written to *pRes as follows:
-**
-**    *pRes<0    This means pCur<pKey
-**
-**    *pRes==0   This means pCur==pKey for all nKey bytes
-**
-**    *pRes>0    This means pCur>pKey
-**
-** When one key is an exact prefix of the other, the shorter key is
-** considered less than the longer one.  In order to be equal the
-** keys must be exactly the same length. (The length of the pCur key
-** is the actual key length minus nIgnore bytes.)
-*/
-static int fileBtreeKeyCompare(
-  BtCursor *pCur,       /* Pointer to entry to compare against */
-  const void *pKey,     /* Key to compare against entry that pCur points to */
-  int nKey,             /* Number of bytes in pKey */
-  int nIgnore,          /* Ignore this many bytes at the end of pCur */
-  int *pResult          /* Write the result here */
-){
-  Pgno nextPage;
-  int n, c, rc, nLocal;
-  Cell *pCell;
-  Btree *pBt = pCur->pBt;
-  const char *zKey  = (const char*)pKey;
-
-  assert( pCur->pPage );
-  assert( pCur->idx>=0 && pCur->idx<pCur->pPage->nCell );
-  pCell = pCur->pPage->apCell[pCur->idx];
-  nLocal = NKEY(pBt, pCell->h) - nIgnore;
-  if( nLocal<0 ) nLocal = 0;
-  n = nKey<nLocal ? nKey : nLocal;
-  if( n>MX_LOCAL_PAYLOAD ){
-    n = MX_LOCAL_PAYLOAD;
-  }
-  c = memcmp(pCell->aPayload, zKey, n);
-  if( c!=0 ){
-    *pResult = c;
-    return SQLITE_OK;
-  }
-  zKey += n;
-  nKey -= n;
-  nLocal -= n;
-  nextPage = SWAB32(pBt, pCell->ovfl);
-  while( nKey>0 && nLocal>0 ){
-    OverflowPage *pOvfl;
-    if( nextPage==0 ){
-      return SQLITE_CORRUPT;
-    }
-    rc = sqlitepager_get(pBt->pPager, nextPage, (void**)&pOvfl);
-    if( rc ){
-      return rc;
-    }
-    nextPage = SWAB32(pBt, pOvfl->iNext);
-    n = nKey<nLocal ? nKey : nLocal;
-    if( n>OVERFLOW_SIZE ){
-      n = OVERFLOW_SIZE;
-    }
-    c = memcmp(pOvfl->aPayload, zKey, n);
-    sqlitepager_unref(pOvfl);
-    if( c!=0 ){
-      *pResult = c;
-      return SQLITE_OK;
-    }
-    nKey -= n;
-    nLocal -= n;
-    zKey += n;
-  }
-  if( c==0 ){
-    c = nLocal - nKey;
-  }
-  *pResult = c;
-  return SQLITE_OK;
+  return getPayload(pCur, offset, amt, pBuf, 1);
 }
 
 /*
 ** Move the cursor down to a new child page.  The newPgno argument is the
 ** page number of the child page in the byte order of the disk image.
 */
-static int moveToChild(BtCursor *pCur, int newPgno){
+static int moveToChild(BtCursor *pCur, u32 newPgno){
   int rc;
   MemPage *pNewPage;
+  MemPage *pOldPage;
+  unsigned char *aData;
   Btree *pBt = pCur->pBt;
 
-  newPgno = SWAB32(pBt, newPgno);
-  rc = sqlitepager_get(pBt->pPager, newPgno, (void**)&pNewPage);
+  rc = getPage(pBt, newPgno, &pNewPage);
   if( rc ) return rc;
-  rc = initPage(pBt, pNewPage, newPgno, pCur->pPage);
+  rc = initPage(pNewPage, pCur->pPage);
   if( rc ) return rc;
-  assert( pCur->idx>=pCur->pPage->nCell
-          || pCur->pPage->apCell[pCur->idx]->h.leftChild==SWAB32(pBt,newPgno) );
-  assert( pCur->idx<pCur->pPage->nCell
-          || pCur->pPage->u.hdr.rightChild==SWAB32(pBt,newPgno) );
   pNewPage->idxParent = pCur->idx;
-  pCur->pPage->idxShift = 0;
-  sqlitepager_unref(pCur->pPage);
+  pOldPage = pCur->pPage;
+  pOldPage->idxShift = 0;
+  releasePage(pOldPage);
   pCur->pPage = pNewPage;
   pCur->idx = 0;
   if( pNewPage->nCell<1 ){
@@ -1465,13 +1532,15 @@ static void moveToParent(BtCursor *pCur){
   MemPage *pParent;
   MemPage *pPage;
   int idxParent;
+
   pPage = pCur->pPage;
   assert( pPage!=0 );
   pParent = pPage->pParent;
   assert( pParent!=0 );
   idxParent = pPage->idxParent;
-  sqlitepager_ref(pParent);
-  sqlitepager_unref(pPage);
+  sqlitepager_ref(pParent->aData);
+  oldPgno = pPage->pgno;
+  releasePage(pPage);
   pCur->pPage = pParent;
   assert( pParent->idxShift==0 );
   if( pParent->idxShift==0 ){
@@ -1480,11 +1549,10 @@ static void moveToParent(BtCursor *pCur){
     /* Verify that pCur->idx is the correct index to point back to the child
     ** page we just came from 
     */
-    oldPgno = SWAB32(pCur->pBt, sqlitepager_pagenumber(pPage));
     if( pCur->idx<pParent->nCell ){
-      assert( pParent->apCell[idxParent]->h.leftChild==oldPgno );
+      assert( get4Byte(&pParent->aCell[idxParent][2])==oldPgno );
     }else{
-      assert( pParent->u.hdr.rightChild==oldPgno );
+      assert( get4Byte(&pParent->aData[pParent->hdrOffset+6])==oldPgno );
     }
 #endif
   }else{
@@ -1495,9 +1563,8 @@ static void moveToParent(BtCursor *pCur){
     */
     int i;
     pCur->idx = pParent->nCell;
-    oldPgno = SWAB32(pCur->pBt, sqlitepager_pagenumber(pPage));
     for(i=0; i<pParent->nCell; i++){
-      if( pParent->apCell[i]->h.leftChild==oldPgno ){
+      if( get4byte(&pParent->aCell[i][2])==oldPgno ){
         pCur->idx = i;
         break;
       }
@@ -1509,16 +1576,16 @@ static void moveToParent(BtCursor *pCur){
 ** Move the cursor to the root page
 */
 static int moveToRoot(BtCursor *pCur){
-  MemPage *pNew;
+  MemPage *pRoot;
   int rc;
   Btree *pBt = pCur->pBt;
 
-  rc = sqlitepager_get(pBt->pPager, pCur->pgnoRoot, (void**)&pNew);
+  rc = sqlitepager_get(pBt->pPager, pCur->pgnoRoot, &pRoot);
   if( rc ) return rc;
-  rc = initPage(pBt, pNew, pCur->pgnoRoot, 0);
+  rc = initPage(pRoot, 0);
   if( rc ) return rc;
-  sqlitepager_unref(pCur->pPage);
-  pCur->pPage = pNew;
+  releasePage(pCur->pPage);
+  pCur->pPage = pRoot;
   pCur->idx = 0;
   return SQLITE_OK;
 }
@@ -1530,8 +1597,11 @@ static int moveToRoot(BtCursor *pCur){
 static int moveToLeftmost(BtCursor *pCur){
   Pgno pgno;
   int rc;
+  MemPage *pPage;
 
-  while( (pgno = pCur->pPage->apCell[pCur->idx]->h.leftChild)!=0 ){
+  while( !(pPage = pCur->pPage)->leaf ){
+    assert( pCur->idx>=0 && pCur->idx<pPage->nPage );
+    pgno = get4byte(pPage->aCell[pCur->idx][2]);
     rc = moveToChild(pCur, pgno);
     if( rc ) return rc;
   }
@@ -1548,13 +1618,15 @@ static int moveToLeftmost(BtCursor *pCur){
 static int moveToRightmost(BtCursor *pCur){
   Pgno pgno;
   int rc;
+  MemPage *pPage;
 
-  while( (pgno = pCur->pPage->u.hdr.rightChild)!=0 ){
-    pCur->idx = pCur->pPage->nCell;
+  while( !(pPage = pCur->pPage)->leaf ){
+    pgno = get4byte(&pPage->aData[pPage->hdrOffset+6]);
+    pCur->idx = pPage->nCell;
     rc = moveToChild(pCur, pgno);
     if( rc ) return rc;
   }
-  pCur->idx = pCur->pPage->nCell - 1;
+  pCur->idx = pPage->nCell - 1;
   return SQLITE_OK;
 }
 
@@ -1562,7 +1634,7 @@ static int moveToRightmost(BtCursor *pCur){
 ** on success.  Set *pRes to 0 if the cursor actually points to something
 ** or set *pRes to 1 if the table is empty.
 */
-static int fileBtreeFirst(BtCursor *pCur, int *pRes){
+int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){
   int rc;
   if( pCur->pPage==0 ) return SQLITE_ABORT;
   rc = moveToRoot(pCur);
@@ -1581,7 +1653,7 @@ static int fileBtreeFirst(BtCursor *pCur, int *pRes){
 ** on success.  Set *pRes to 0 if the cursor actually points to something
 ** or set *pRes to 1 if the table is empty.
 */
-static int fileBtreeLast(BtCursor *pCur, int *pRes){
+int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
   int rc;
   if( pCur->pPage==0 ) return SQLITE_ABORT;
   rc = moveToRoot(pCur);
@@ -1597,9 +1669,14 @@ static int fileBtreeLast(BtCursor *pCur, int *pRes){
   return rc;
 }
 
-/* Move the cursor so that it points to an entry near pKey.
+/* Move the cursor so that it points to an entry near pKey/nKey.
 ** Return a success code.
 **
+** For INTKEY tables, only the nKey parameter is used.  pKey is
+** ignored.  For other tables, nKey is the number of bytes of data
+** in nKey.  The comparison function specified when the cursor was
+** created is used to compare keys.
+**
 ** 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
 ** were present.  The cursor might point to an entry that comes
@@ -1620,8 +1697,7 @@ static int fileBtreeLast(BtCursor *pCur, int *pRes){
 **     *pRes>0      The cursor is left pointing at an entry that
 **                  is larger than pKey.
 */
-static
-int fileBtreeMoveto(BtCursor *pCur, const void *pKey, int nKey, int *pRes){
+int sqlite3BtreeMoveto(BtCursor *pCur, const void *pKey, u64 nKey, int *pRes){
   int rc;
   if( pCur->pPage==0 ) return SQLITE_ABORT;
   pCur->eSkip = SKIP_NONE;
@@ -1635,9 +1711,28 @@ int fileBtreeMoveto(BtCursor *pCur, const void *pKey, int nKey, int *pRes){
     lwr = 0;
     upr = pPage->nCell-1;
     while( lwr<=upr ){
+      void *pCellKey;
+      u64 nCellKey;
       pCur->idx = (lwr+upr)/2;
-      rc = fileBtreeKeyCompare(pCur, pKey, nKey, 0, &c);
-      if( rc ) return rc;
+      nCellKey = sqlite3BtreeKeySize(pCur, &nCellKey);
+      if( pPage->intKey ){
+        if( nCellKey<nKey ){
+          c = -1;
+        }else if( nCellKey>nKey ){
+          c = +1;
+        }else{
+          c = 0;
+        }
+      }else if( (pCellKey = sqlite3BtreeKeyFetch(pCur))!=0 ){
+        c = pCur->xCompare(pCur->pArg, nCellKey, pCellKey, nKey, pKey);
+      }else{
+        pCellKey = sqliteMalloc( nCellKey );
+        if( pCellKey==0 ) return SQLITE_NOMEM;
+        rc = sqlite3BtreeKey(pCur, 0, nCellKey, pCellKey);
+        c = pCur->xCompare(pCur->pArg, nCellKey, pCellKey, nKey, pKey);
+        sqliteFree(pCellKey);
+        if( rc ) return rc;
+      }
       if( c==0 ){
         pCur->iMatch = c;
         if( pRes ) *pRes = 0;
@@ -1651,10 +1746,12 @@ int fileBtreeMoveto(BtCursor *pCur, const void *pKey, int nKey, int *pRes){
     }
     assert( lwr==upr+1 );
     assert( pPage->isInit );
-    if( lwr>=pPage->nCell ){
-      chldPg = pPage->u.hdr.rightChild;
+    if( pPage->leaf ){
+      chldpg = 0;
+    }else if( lwr>=pPage->nCell ){
+      chldPg = get4byte(&pPage->aData[pPage->hdrOffset+6]);
     }else{
-      chldPg = pPage->apCell[lwr]->h.leftChild;
+      chldPg = get4byte(&pPage->aCell[lwr][2]);
     }
     if( chldPg==0 ){
       pCur->iMatch = c;
@@ -1674,7 +1771,7 @@ int fileBtreeMoveto(BtCursor *pCur, const void *pKey, int nKey, int *pRes){
 ** was already pointing to the last entry in the database before
 ** this routine was called, then set *pRes=1.
 */
-static int fileBtreeNext(BtCursor *pCur, int *pRes){
+int sqlite3BtreeNext(BtCursor *pCur, int *pRes){
   int rc;
   MemPage *pPage = pCur->pPage;
   assert( pRes!=0 );
@@ -1697,8 +1794,8 @@ static int fileBtreeNext(BtCursor *pCur, int *pRes){
   pCur->eSkip = SKIP_NONE;
   pCur->idx++;
   if( pCur->idx>=pPage->nCell ){
-    if( pPage->u.hdr.rightChild ){
-      rc = moveToChild(pCur, pPage->u.hdr.rightChild);
+    if( !pPage->left ){
+      rc = moveToChild(pCur, get4byte(&pPage->aData[pPage->hdrOffset+6]);
       if( rc ) return rc;
       rc = moveToLeftmost(pCur);
       *pRes = 0;
@@ -1716,7 +1813,7 @@ static int fileBtreeNext(BtCursor *pCur, int *pRes){
     return SQLITE_OK;
   }
   *pRes = 0;
-  if( pPage->u.hdr.rightChild==0 ){
+  if( pPage->leaf ){
     return SQLITE_OK;
   }
   rc = moveToLeftmost(pCur);
@@ -1729,7 +1826,7 @@ static int fileBtreeNext(BtCursor *pCur, int *pRes){
 ** was already pointing to the first entry in the database before
 ** this routine was called, then set *pRes=1.
 */
-static int fileBtreePrevious(BtCursor *pCur, int *pRes){
+int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){
   int rc;
   Pgno pgno;
   MemPage *pPage;
@@ -1751,7 +1848,8 @@ static int fileBtreePrevious(BtCursor *pCur, int *pRes){
   }
   pCur->eSkip = SKIP_NONE;
   assert( pCur->idx>=0 );
-  if( (pgno = pPage->apCell[pCur->idx]->h.leftChild)!=0 ){
+  if( !pPage->left ){
+    pgno = get4byte(&pPage->aCell[pCur->idx][2]);
     rc = moveToChild(pCur, pgno);
     if( rc ) return rc;
     rc = moveToRightmost(pCur);
@@ -1789,227 +1887,239 @@ static int fileBtreePrevious(BtCursor *pCur, int *pRes){
 ** which in turn can make database access faster.
 */
 static int allocatePage(Btree *pBt, MemPage **ppPage, Pgno *pPgno, Pgno nearby){
-  PageOne *pPage1 = pBt->page1;
+  u32 pn;
+  MemPage *pPage1;
+  MemPage *pPage;
   int rc;
-  if( pPage1->freeList ){
-    OverflowPage *pOvfl;
-    FreelistInfo *pInfo;
-
-    rc = sqlitepager_write(pPage1);
+  int n;     /* Number of pages on the freelist */
+  int k;     /* Number of leaves on the trunk of the freelist */
+
+  pPage1 = pBt->pPage1;
+  n = get4byte(&pPage1->aData[36]);
+  if( n>0 ){
+    /* There exists pages on the freelist.  Reuse one of those pages. */
+    MemPage *pTrunk;
+    rc = sqlitepager_write(pPage1->aData);
     if( rc ) return rc;
-    SWAB_ADD(pBt, pPage1->nFree, -1);
-    rc = sqlitepager_get(pBt->pPager, SWAB32(pBt, pPage1->freeList),
-                        (void**)&pOvfl);
+    put4byte(&pPage1->aData[36], n-1);
+    rc = getPage(pBt, get4byte(&pPage1->aData[32]), &pTrunk);
     if( rc ) return rc;
-    rc = sqlitepager_write(pOvfl);
+    rc = sqlitepager_write(pTrunk->aData);
     if( rc ){
-      sqlitepager_unref(pOvfl);
+      releasePage(pTrunk);
       return rc;
     }
-    pInfo = (FreelistInfo*)pOvfl->aPayload;
-    if( pInfo->nFree==0 ){
-      *pPgno = SWAB32(pBt, pPage1->freeList);
-      pPage1->freeList = pOvfl->iNext;
-      *ppPage = (MemPage*)pOvfl;
+    k = get4byte(&pTrunk->aData[4]);
+    if( k==0 ){
+      /* The trunk has no leaves.  So extract the trunk page itself and
+      ** use it as the newly allocated page */
+      *pPgno = get4byte(pPage1->aData[32]);
+      memcpy(&pPage1->aData[32], &pTrunk->aData[0], 4);
+      *ppPage = pTrunk;
     }else{
-      int closest, n;
-      n = SWAB32(pBt, pInfo->nFree);
-      if( n>1 && nearby>0 ){
+      /* Extract a leaf from the trunk */
+      int closest;
+      unsigned char *aData = pTrunk->aData;
+      if( nearby>0 ){
         int i, dist;
         closest = 0;
-        dist = SWAB32(pBt, pInfo->aFree[0]) - nearby;
+        dist = get4byte(&aData[8]) - nearby;
         if( dist<0 ) dist = -dist;
         for(i=1; i<n; i++){
-          int d2 = SWAB32(pBt, pInfo->aFree[i]) - nearby;
+          int d2 = get4byte(&aData[8+i*4]) - nearby;
           if( d2<0 ) d2 = -d2;
           if( d2<dist ) closest = i;
         }
       }else{
         closest = 0;
       }
-      SWAB_ADD(pBt, pInfo->nFree, -1);
-      *pPgno = SWAB32(pBt, pInfo->aFree[closest]);
-      pInfo->aFree[closest] = pInfo->aFree[n-1];
-      rc = sqlitepager_get(pBt->pPager, *pPgno, (void**)ppPage);
-      sqlitepager_unref(pOvfl);
+      put4byte(&aData[4], n-1);
+      *pPgno = get4data(&aData[8+closest*4]);
+      memcpy(&aData[8+closest*4], &aData[4+closest*n], 4);
+      rc = getPage(pBt, *pPgno, ppPage);
+      releasePage(pTrunk);
       if( rc==SQLITE_OK ){
         sqlitepager_dont_rollback(*ppPage);
-        rc = sqlitepager_write(*ppPage);
+        rc = sqlitepager_write((*ppPage)->aData);
       }
     }
   }else{
+    /* There are no pages on the freelist, so create a new page at the
+    ** end of the file */
     *pPgno = sqlitepager_pagecount(pBt->pPager) + 1;
-    rc = sqlitepager_get(pBt->pPager, *pPgno, (void**)ppPage);
+    rc = getPage(pBt, *pPgno, ppPage);
     if( rc ) return rc;
-    rc = sqlitepager_write(*ppPage);
+    rc = sqlitepager_write((*ppPage)->aData);
   }
   return rc;
 }
 
 /*
-** Add a page of the database file to the freelist.  Either pgno or
-** pPage but not both may be 0. 
+** Add a page of the database file to the freelist.
 **
 ** sqlitepager_unref() is NOT called for pPage.
 */
-static int freePage(Btree *pBt, void *pPage, Pgno pgno){
-  PageOne *pPage1 = pBt->page1;
-  OverflowPage *pOvfl = (OverflowPage*)pPage;
-  int rc;
-  int needUnref = 0;
-  MemPage *pMemPage;
-
-  if( pgno==0 ){
-    assert( pOvfl!=0 );
-    pgno = sqlitepager_pagenumber(pOvfl);
-  }
-  assert( pgno>2 );
-  assert( sqlitepager_pagenumber(pOvfl)==pgno );
-  pMemPage = (MemPage*)pPage;
-  pMemPage->isInit = 0;
-  if( pMemPage->pParent ){
-    sqlitepager_unref(pMemPage->pParent);
-    pMemPage->pParent = 0;
-  }
-  rc = sqlitepager_write(pPage1);
-  if( rc ){
-    return rc;
-  }
-  SWAB_ADD(pBt, pPage1->nFree, 1);
-  if( pPage1->nFree!=0 && pPage1->freeList!=0 ){
-    OverflowPage *pFreeIdx;
-    rc = sqlitepager_get(pBt->pPager, SWAB32(pBt, pPage1->freeList),
-                        (void**)&pFreeIdx);
-    if( rc==SQLITE_OK ){
-      FreelistInfo *pInfo = (FreelistInfo*)pFreeIdx->aPayload;
-      int n = SWAB32(pBt, pInfo->nFree);
-      if( n<(sizeof(pInfo->aFree)/sizeof(pInfo->aFree[0])) ){
-        rc = sqlitepager_write(pFreeIdx);
-        if( rc==SQLITE_OK ){
-          pInfo->aFree[n] = SWAB32(pBt, pgno);
-          SWAB_ADD(pBt, pInfo->nFree, 1);
-          sqlitepager_unref(pFreeIdx);
-          sqlitepager_dont_write(pBt->pPager, pgno);
-          return rc;
-        }
-      }
-      sqlitepager_unref(pFreeIdx);
-    }
-  }
-  if( pOvfl==0 ){
-    assert( pgno>0 );
-    rc = sqlitepager_get(pBt->pPager, pgno, (void**)&pOvfl);
+static int freePage(MemPage *pPage){
+  Btree *pBt = pPage->pBt;
+  MemPage *pPage1 = pBt->pPage1;
+  int rc, n, k;
+
+  /* Prepare the page for freeing */
+  assert( pPage->pgno>1 );
+  pPage->isInit = 0;
+  releasePage(pPage->pParent);
+  pPage->pParent = 0;
+
+  /* Increment the free page count on page1 */
+  rc = sqlitepager_write(pPage1->aData);
+  if( rc ) return rc;
+  n = get4byte(&pPage1->aData[36]);
+  put4byte(&pPage1->aData[36], n+1);
+
+  if( n==0 ){
+    /* This is the first free page */
+    memset(pPage->aData, 0, 8);
+    put4byte(pPage1->aData[32], pPage->pgno);
+  }else{
+    /* Other free pages already exist.  Retrive the first trunk page
+    ** of the freelist and find out how many leaves it has. */
+    MemPage *pTrunk
+    rc = getPage(pBt, get4byte(pPage1->aData[32], &pTrunk);
     if( rc ) return rc;
-    needUnref = 1;
-  }
-  rc = sqlitepager_write(pOvfl);
-  if( rc ){
-    if( needUnref ) sqlitepager_unref(pOvfl);
-    return rc;
+    k = get4byte(&pTrunk->aData[4]);
+    if( k==pBt->pageSize/4 - 8 ){
+      /* The trunk is full.  Turn the page being freed into a new
+      ** trunk page with no leaves. */
+      rc = sqlitepager_write(pPage->aData);
+      if( rc ) return rc;
+      put4byte(pPage->aData, pTrunk->pgno);
+      put4byte(&pPage->aData[4], 0);
+      put4byte(&pPage1->aData[32], pPage->pgno);
+    }else{
+      /* Add the newly freed page as a leaf on the current trunk */
+      rc = sqlitepager_write(pTrunk->aData);
+      if( rc ) return rc;
+      put4byte(&pTrunk->aData[4], k+1);
+      put4byte(&pTrunk->aData[8+k*4], pPage->pgno);
+      sqlitepager_dont_write(pBt->pPager, pPage->pgno);
+    }
+    releasePage(pTrunk);
   }
-  pOvfl->iNext = pPage1->freeList;
-  pPage1->freeList = SWAB32(pBt, pgno);
-  memset(pOvfl->aPayload, 0, OVERFLOW_SIZE);
-  if( needUnref ) rc = sqlitepager_unref(pOvfl);
   return rc;
 }
 
 /*
-** Erase all the data out of a cell.  This involves returning overflow
-** pages back the freelist.
+** Free any overflow pages associated with the given Cell.
 */
-static int clearCell(Btree *pBt, Cell *pCell){
-  Pager *pPager = pBt->pPager;
-  OverflowPage *pOvfl;
-  Pgno ovfl, nextOvfl;
-  int rc;
+static int clearCell(MemPage *pPage, unsigned char *pCell){
+  Btree *pBt = pPage->pBt;
+  int rc, n;
+  u64 nData, nKey;
+  Pgno ovflPgno;
 
-  if( NKEY(pBt, pCell->h) + NDATA(pBt, pCell->h) <= MX_LOCAL_PAYLOAD ){
-    return SQLITE_OK;
+  parseCellHeader(pPage, pCell, &nData, &nKey, &n);
+  nPayload = nData;
+  if( !pPage->intKey ){
+    nPayload += nKey;
   }
-  ovfl = SWAB32(pBt, pCell->ovfl);
-  pCell->ovfl = 0;
-  while( ovfl ){
-    rc = sqlitepager_get(pPager, ovfl, (void**)&pOvfl);
+  if( nPayload<=pBt->maxLocal ){
+    return;  /* There are no overflow pages.  Return without doing anything */
+  }
+  ovflPgno = get4byte(&pCell[n+pBt->maxLocal]);
+  while( ovflPgno!=0 ){
+    MemPage *pOvfl;
+    rc = getPage(pBt, ovflPgno, &pOvfl);
     if( rc ) return rc;
-    nextOvfl = SWAB32(pBt, pOvfl->iNext);
+    ovflPgno = get4byte(pOvfl->aData);
     rc = freePage(pBt, pOvfl, ovfl);
     if( rc ) return rc;
-    sqlitepager_unref(pOvfl);
-    ovfl = nextOvfl;
+    sqlitepager_unref(pOvfl->aData);
   }
   return SQLITE_OK;
 }
 
 /*
-** Create a new cell from key and data.  Overflow pages are allocated as
-** necessary and linked to this cell.  
+** Compute the number of bytes required by a cell header.  If the *pHeader
+** argument is not NULL, fill it in with the bytes of the header.
+*/
+static int makeCellHeader(
+  MemPage *pPage,          /* The page that will contain the cell */
+  u64 nKey,                /* Size of key, or the key value if intKey */
+  int nData,               /* Size of data.  Ignored for zerodata */
+  unsigned char *pHeader   /* Write header bytes here */
+){
+  int n = 2;
+  if( !pPage->leaf ) n += 4;
+  if( !pPage->zeroData ){
+    n += putVarint(&pHeader[n], nData);
+  }
+  n += putVarint(&pHeader[n], nKey);
+  return n;
+}
+
+/*
+** Fill in the payload section of a cell into the space provided.  If
+** the payload will not completely fit in the cell, allocate additional
+** overflow pages and fill them in.
 */
 static int fillInCell(
-  Btree *pBt,              /* The whole Btree.  Needed to allocate pages */
-  Cell *pCell,             /* Populate this Cell structure */
-  const void *pKey, int nKey,    /* The key */
+  MemPage *pPage,                /* The page that contains the cell */
+  unsigned char *pCell,          /* Pointer to start of payload area */
+  int nHeader,                   /* Number of bytes in the cell header */
+  const void *pKey, u64 nKey,    /* The key */
   const void *pData,int nData    /* The data */
 ){
-  OverflowPage *pOvfl, *pPrior;
-  Pgno *pNext;
-  int spaceLeft;
-  int n, rc;
   int nPayload;
-  const char *pPayload;
-  char *pSpace;
-  Pgno nearby = 0;
-
-  pCell->h.leftChild = 0;
-  pCell->h.nKey = SWAB16(pBt, nKey & 0xffff);
-  pCell->h.nKeyHi = nKey >> 16;
-  pCell->h.nData = SWAB16(pBt, nData & 0xffff);
-  pCell->h.nDataHi = nData >> 16;
-  pCell->h.iNext = 0;
-
-  pNext = &pCell->ovfl;
-  pSpace = pCell->aPayload;
-  spaceLeft = MX_LOCAL_PAYLOAD;
-  pPayload = pKey;
-  pKey = 0;
-  nPayload = nKey;
-  pPrior = 0;
+  const void *pSrc;
+  int nSrc, nSrc2;
+  int spaceLeft;
+  MemPage *pOvfl = 0;
+  unsigned char *pPrior;
+  unsigned char *pPayload;
+  Btree *pBt = pPage->pBt;
+  Pgno pgnoOvfl = 0;
+
+  nPayload = nData;
+  if( pPage->intKey ){
+    pSrc = pData;
+    nSrc = nData;
+    nSrc2 = 0;
+  }else{
+    nPayload += nKey;
+    pSrc = pKey;
+    nSrc = nKey;
+  }
+  spaceLeft = pBt->maxLocal;
+  pPayload = &pCell[nHeader];
+  pPrior = &pPayload[pBt->maxLocal];
+
   while( nPayload>0 ){
     if( spaceLeft==0 ){
-      rc = allocatePage(pBt, (MemPage**)&pOvfl, pNext, nearby);
-      if( rc ){
-        *pNext = 0;
-      }else{
-        nearby = *pNext;
-      }
-      if( pPrior ) sqlitepager_unref(pPrior);
+      rc =  allocatePage(pBt, &pOvfl, &pgnoOvfl, pgnoOvfl);
       if( rc ){
-        clearCell(pBt, pCell);
+        clearCell(pPage, pCell);
         return rc;
       }
-      if( pBt->needSwab ) *pNext = swab32(*pNext);
-      pPrior = pOvfl;
-      spaceLeft = OVERFLOW_SIZE;
-      pSpace = pOvfl->aPayload;
-      pNext = &pOvfl->iNext;
+      put4byte(pPrior, pgnoOvfl);
+      pPrior = pOvfl->aData;
+      put4byte(pPrior, 0);
+      pPayload = &pOvfl->aData[4];
+      spaceLeft = pBt->pageSize - 4;
     }
     n = nPayload;
     if( n>spaceLeft ) n = spaceLeft;
-    memcpy(pSpace, pPayload, n);
+    if( n>nSrc ) n = nSrc;
+    memcpy(pPayload, pSrc, n);
     nPayload -= n;
-    if( nPayload==0 && pData ){
-      pPayload = pData;
-      nPayload = nData;
-      pData = 0;
-    }else{
-      pPayload += n;
-    }
+    nSrc -= n;
     spaceLeft -= n;
-    pSpace += n;
-  }
-  *pNext = 0;
-  if( pPrior ){
-    sqlitepager_unref(pPrior);
+    if( nSrc==0 ){
+      nSrc = nData;
+      pSrc = pData;
+    }
+    if( pOvfl && (spaceLeft==0 || nPayload==0) ){
+      releasePage(pOvfl);
+    }
   }
   return SQLITE_OK;
 }
@@ -2655,7 +2765,7 @@ static int checkReadLocks(BtCursor *pCur){
 ** define what database the record should be inserted into.  The cursor
 ** is left pointing at the new record.
 */
-static int fileBtreeInsert(
+int sqlite3BtreeInsert(
   BtCursor *pCur,                /* Insert data into the table of this cursor */
   const void *pKey, int nKey,    /* The key of the new record */
   const void *pData, int nData   /* The data of the new record */
@@ -2681,7 +2791,7 @@ static int fileBtreeInsert(
   if( checkReadLocks(pCur) ){
     return SQLITE_LOCKED; /* The table pCur points to has a read lock */
   }
-  rc = fileBtreeMoveto(pCur, pKey, nKey, &loc);
+  rc = sqlite3BtreeMoveto(pCur, pKey, nKey, &loc);
   if( rc ) return rc;
   pPage = pCur->pPage;
   assert( pPage->isInit );
@@ -2723,7 +2833,7 @@ static int fileBtreeInsert(
 ** sqliteBtreePrevious() will always leave the cursor pointing at the
 ** entry immediately before the one that was deleted.
 */
-static int fileBtreeDelete(BtCursor *pCur){
+int sqlite3BtreeDelete(BtCursor *pCur){
   MemPage *pPage = pCur->pPage;
   Cell *pCell;
   int rc;
@@ -2766,7 +2876,7 @@ static int fileBtreeDelete(BtCursor *pCur){
     int szNext;
     int notUsed;
     getTempCursor(pCur, &leafCur);
-    rc = fileBtreeNext(&leafCur, &notUsed);
+    rc = sqlite3BtreeNext(&leafCur, &notUsed);
     if( rc!=SQLITE_OK ){
       if( rc!=SQLITE_NOMEM ) rc = SQLITE_CORRUPT;
       return rc;
@@ -2812,7 +2922,7 @@ static int fileBtreeDelete(BtCursor *pCur){
 ** BTree indices are restricted to having an arbitrary key and no data.
 ** But for now, this routine also serves to create indices.
 */
-static int fileBtreeCreateTable(Btree *pBt, int *piTable){
+int sqlite3BtreeCreateTable(Btree *pBt, int *piTable, int flags){
   MemPage *pRoot;
   Pgno pgnoRoot;
   int rc;
@@ -2875,7 +2985,7 @@ static int clearDatabasePage(Btree *pBt, Pgno pgno, int freePageFlag){
 /*
 ** Delete all information from a single table in the database.
 */
-static int fileBtreeClearTable(Btree *pBt, int iTable){
+int sqlite3BtreeClearTable(Btree *pBt, int iTable){
   int rc;
   BtCursor *pCur;
   if( !pBt->inTrans ){
@@ -2889,7 +2999,7 @@ static int fileBtreeClearTable(Btree *pBt, int iTable){
   }
   rc = clearDatabasePage(pBt, (Pgno)iTable, 0);
   if( rc ){
-    fileBtreeRollback(pBt);
+    sqlite3BtreeRollback(pBt);
   }
   return rc;
 }
@@ -2899,7 +3009,7 @@ static int fileBtreeClearTable(Btree *pBt, int iTable){
 ** the freelist.  Except, the root of the principle table (the one on
 ** page 2) is never added to the freelist.
 */
-static int fileBtreeDropTable(Btree *pBt, int iTable){
+int sqlite3BtreeDropTable(Btree *pBt, int iTable){
   int rc;
   MemPage *pPage;
   BtCursor *pCur;
@@ -2913,7 +3023,7 @@ static int fileBtreeDropTable(Btree *pBt, int iTable){
   }
   rc = sqlitepager_get(pBt->pPager, (Pgno)iTable, (void**)&pPage);
   if( rc ) return rc;
-  rc = fileBtreeClearTable(pBt, iTable);
+  rc = sqlite3BtreeClearTable(pBt, iTable);
   if( rc ) return rc;
   if( iTable>2 ){
     rc = freePage(pBt, pPage, iTable);
@@ -3026,8 +3136,7 @@ static int copyDatabasePage(
 /*
 ** Read the meta-information out of a database file.
 */
-static int fileBtreeGetMeta(Btree *pBt, int *aMeta){
-  PageOne *pP1;
+int sqlite3BtreeGetMeta(Btree *pBt, int idx, u32 *pMeta){
   int rc;
   int i;
 
@@ -3044,7 +3153,7 @@ static int fileBtreeGetMeta(Btree *pBt, int *aMeta){
 /*
 ** Write meta-information back into the database.
 */
-static int fileBtreeUpdateMeta(Btree *pBt, int *aMeta){
+int sqlite3BtreeUpdateMeta(Btree *pBt, int idx, u32 iMeta){
   PageOne *pP1;
   int rc, i;
   if( !pBt->inTrans ){
@@ -3188,7 +3297,7 @@ static int fileBtreeCursorDump(BtCursor *pCur, int *aResult){
 ** Return the pager associated with a BTree.  This routine is used for
 ** testing and debugging only.
 */
-static Pager *fileBtreePager(Btree *pBt){
+Pager *sqlite3BtreePager(Btree *pBt){
   return pBt->pPager;
 }
 
@@ -3460,7 +3569,7 @@ static int checkTreePage(
 ** and a pointer to that error message is returned.  The calling function
 ** is responsible for freeing the error message when it is done.
 */
-char *fileBtreeIntegrityCheck(Btree *pBt, int *aRoot, int nRoot){
+char *sqlite3BtreeIntegrityCheck(Btree *pBt, int *aRoot, int nRoot){
   int i;
   int nRef;
   IntegrityCk sCheck;
@@ -3524,7 +3633,7 @@ char *fileBtreeIntegrityCheck(Btree *pBt, int *aRoot, int nRoot){
 /*
 ** Return the full pathname of the underlying database file.
 */
-static const char *fileBtreeGetFilename(Btree *pBt){
+const char *sqlite3BtreeGetFilename(Btree *pBt){
   assert( pBt->pPager!=0 );
   return sqlitepager_filename(pBt->pPager);
 }
@@ -3536,7 +3645,7 @@ static const char *fileBtreeGetFilename(Btree *pBt){
 ** The size of file pBtFrom may be reduced by this operation.
 ** If anything goes wrong, the transaction on pBtFrom is rolled back.
 */
-static int fileBtreeCopyFile(Btree *pBtTo, Btree *pBtFrom){
+int sqlite3BtreeCopyFile(Btree *pBtTo, Btree *pBtFrom){
   int rc = SQLITE_OK;
   Pgno i, nPage, nToPage;
 
@@ -3567,57 +3676,7 @@ static int fileBtreeCopyFile(Btree *pBtTo, Btree *pBtFrom){
     rc = sqlitepager_truncate(pBtTo->pPager, nPage);
   }
   if( rc ){
-    fileBtreeRollback(pBtTo);
+    sqlite3BtreeRollback(pBtTo);
   }
   return rc;  
 }
-
-/*
-** The following tables contain pointers to all of the interface
-** routines for this implementation of the B*Tree backend.  To
-** substitute a different implemention of the backend, one has merely
-** to provide pointers to alternative functions in similar tables.
-*/
-static BtOps sqliteBtreeOps = {
-    fileBtreeClose,
-    fileBtreeSetCacheSize,
-    fileBtreeSetSafetyLevel,
-    fileBtreeBeginTrans,
-    fileBtreeCommit,
-    fileBtreeRollback,
-    fileBtreeBeginCkpt,
-    fileBtreeCommitCkpt,
-    fileBtreeRollbackCkpt,
-    fileBtreeCreateTable,
-    fileBtreeCreateTable,  /* Really sqliteBtreeCreateIndex() */
-    fileBtreeDropTable,
-    fileBtreeClearTable,
-    fileBtreeCursor,
-    fileBtreeGetMeta,
-    fileBtreeUpdateMeta,
-    fileBtreeIntegrityCheck,
-    fileBtreeGetFilename,
-    fileBtreeCopyFile,
-    fileBtreePager,
-#ifdef SQLITE_TEST
-    fileBtreePageDump,
-#endif
-};
-static BtCursorOps sqliteBtreeCursorOps = {
-    fileBtreeMoveto,
-    fileBtreeDelete,
-    fileBtreeInsert,
-    fileBtreeFirst,
-    fileBtreeLast,
-    fileBtreeNext,
-    fileBtreePrevious,
-    fileBtreeKeySize,
-    fileBtreeKey,
-    fileBtreeKeyCompare,
-    fileBtreeDataSize,
-    fileBtreeData,
-    fileBtreeCloseCursor,
-#ifdef SQLITE_TEST
-    fileBtreeCursorDump,
-#endif
-};
index 7b11da6f69b3eb955349975b139c692750970e57..8e32e2ab9760d0516064a16d6e84f731db2a9713 100644 (file)
@@ -13,7 +13,7 @@
 ** subsystem.  See comments in the source code for a detailed description
 ** of what each interface routine does.
 **
-** @(#) $Id: btree.h,v 1.36 2004/02/10 02:57:59 drh Exp $
+** @(#) $Id: btree.h,v 1.37 2004/04/26 14:10:21 drh Exp $
 */
 #ifndef _BTREE_H_
 #define _BTREE_H_
 */
 typedef struct Btree Btree;
 typedef struct BtCursor BtCursor;
-typedef struct BtOps BtOps;
-typedef struct BtCursorOps BtCursorOps;
 
 
-/*
-** An instance of the following structure contains pointers to all
-** methods against an open BTree.  Alternative BTree implementations
-** (examples: file based versus in-memory) can be created by substituting
-** different methods.  Users of the BTree cannot tell the difference.
-**
-** In C++ we could do this by defining a virtual base class and then
-** creating subclasses for each different implementation.  But this is
-** C not C++ so we have to be a little more explicit.
-*/
-struct BtOps {
-    int (*Close)(Btree*);
-    int (*SetCacheSize)(Btree*, int);
-    int (*SetSafetyLevel)(Btree*, int);
-    int (*BeginTrans)(Btree*);
-    int (*Commit)(Btree*);
-    int (*Rollback)(Btree*);
-    int (*BeginCkpt)(Btree*);
-    int (*CommitCkpt)(Btree*);
-    int (*RollbackCkpt)(Btree*);
-    int (*CreateTable)(Btree*, int*);
-    int (*CreateIndex)(Btree*, int*);
-    int (*DropTable)(Btree*, int);
-    int (*ClearTable)(Btree*, int);
-    int (*Cursor)(Btree*, int iTable, int wrFlag, BtCursor **ppCur);
-    int (*GetMeta)(Btree*, int*);
-    int (*UpdateMeta)(Btree*, int*);
-    char *(*IntegrityCheck)(Btree*, int*, int);
-    const char *(*GetFilename)(Btree*);
-    int (*Copyfile)(Btree*,Btree*);
-    struct Pager *(*Pager)(Btree*);
-#ifdef SQLITE_TEST
-    int (*PageDump)(Btree*, int, int);
-#endif
-};
+int sqlite3BtreeOpen(const char *zFilename, Btree **, int nCache, int flags);
 
-/*
-** An instance of this structure defines all of the methods that can
-** be executed against a cursor.
+/* The flags parameter to sqlite3BtreeOpen can be the bitwise or of the
+** following values.
 */
-struct BtCursorOps {
-    int (*Moveto)(BtCursor*, const void *pKey, int nKey, int *pRes);
-    int (*Delete)(BtCursor*);
-    int (*Insert)(BtCursor*, const void *pKey, int nKey,
-                             const void *pData, int nData);
-    int (*First)(BtCursor*, int *pRes);
-    int (*Last)(BtCursor*, int *pRes);
-    int (*Next)(BtCursor*, int *pRes);
-    int (*Previous)(BtCursor*, int *pRes);
-    int (*KeySize)(BtCursor*, int *pSize);
-    int (*Key)(BtCursor*, int offset, int amt, char *zBuf);
-    int (*KeyCompare)(BtCursor*, const void *pKey, int nKey,
-                                 int nIgnore, int *pRes);
-    int (*DataSize)(BtCursor*, int *pSize);
-    int (*Data)(BtCursor*, int offset, int amt, char *zBuf);
-    int (*CloseCursor)(BtCursor*);
-#ifdef SQLITE_TEST
-    int (*CursorDump)(BtCursor*, int*);
-#endif
-};
+#define BTREE_OMIT_JOURNAL  1  /* Do not use journal.  No argument */
+#define BTREE_MEMORY        2  /* In-memory DB.  No argument */
 
-/*
-** The number of 4-byte "meta" values contained on the first page of each
-** database file.
-*/
-#define SQLITE_N_BTREE_META 10
+int sqlite3BtreeClose(Btree*);
+int sqlite3BtreeSetCacheSize(Btree*,int);
+int sqlite3BtreeSetSafetyLevel(Btree*,int);
+int sqlite3BtreeBeginTrans(Btree*);
+int sqlite3BtreeCommit(Btree*);
+int sqlite3BtreeRollback(Btree*);
+int sqlite3BtreeBeginStmt(Btree*);
+int sqlite3BtreeCommitStmt(Btree*);
+int sqlite3BtreeRollbackStmt(Btree*);
+int sqlite3BtreeCreateTable(Btree*, int*, int flags);
 
-int sqliteBtreeOpen(const char *zFilename, int mode, int nPg, Btree **ppBtree);
-int sqliteRbtreeOpen(const char *zFilename, int mode, int nPg, Btree **ppBtree);
+/* The flags parameter to sqlite3BtreeCreateTable can be the bitwise OR
+** of the following flags:
+*/
+#define BTREE_INTKEY     1      /* Table has only 64-bit integer keys */
+#define BTREE_ZERODATA   2      /* Table has keys only - no data */
 
-#define btOps(pBt) (*((BtOps **)(pBt)))
-#define btCOps(pCur) (*((BtCursorOps **)(pCur)))
+int sqlite3BtreeDropTable(Btree*, int);
+int sqlite3BtreeClearTable(Btree*, int);
+int sqlite3BtreeGetMeta(Btree*, int idx, u32 *pValue);
+int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value);
 
-#define sqliteBtreeClose(pBt)              (btOps(pBt)->Close(pBt))
-#define sqliteBtreeSetCacheSize(pBt, sz)   (btOps(pBt)->SetCacheSize(pBt, sz))
-#define sqliteBtreeSetSafetyLevel(pBt, sl) (btOps(pBt)->SetSafetyLevel(pBt, sl))
-#define sqliteBtreeBeginTrans(pBt)         (btOps(pBt)->BeginTrans(pBt))
-#define sqliteBtreeCommit(pBt)             (btOps(pBt)->Commit(pBt))
-#define sqliteBtreeRollback(pBt)           (btOps(pBt)->Rollback(pBt))
-#define sqliteBtreeBeginCkpt(pBt)          (btOps(pBt)->BeginCkpt(pBt))
-#define sqliteBtreeCommitCkpt(pBt)         (btOps(pBt)->CommitCkpt(pBt))
-#define sqliteBtreeRollbackCkpt(pBt)       (btOps(pBt)->RollbackCkpt(pBt))
-#define sqliteBtreeCreateTable(pBt,piTable)\
-                (btOps(pBt)->CreateTable(pBt,piTable))
-#define sqliteBtreeCreateIndex(pBt, piIndex)\
-                (btOps(pBt)->CreateIndex(pBt, piIndex))
-#define sqliteBtreeDropTable(pBt, iTable) (btOps(pBt)->DropTable(pBt, iTable))
-#define sqliteBtreeClearTable(pBt, iTable)\
-                (btOps(pBt)->ClearTable(pBt, iTable))
-#define sqliteBtreeCursor(pBt, iTable, wrFlag, ppCur)\
-                (btOps(pBt)->Cursor(pBt, iTable, wrFlag, ppCur))
-#define sqliteBtreeMoveto(pCur, pKey, nKey, pRes)\
-                (btCOps(pCur)->Moveto(pCur, pKey, nKey, pRes))
-#define sqliteBtreeDelete(pCur)           (btCOps(pCur)->Delete(pCur))
-#define sqliteBtreeInsert(pCur, pKey, nKey, pData, nData) \
-                (btCOps(pCur)->Insert(pCur, pKey, nKey, pData, nData))
-#define sqliteBtreeFirst(pCur, pRes)      (btCOps(pCur)->First(pCur, pRes))
-#define sqliteBtreeLast(pCur, pRes)       (btCOps(pCur)->Last(pCur, pRes))
-#define sqliteBtreeNext(pCur, pRes)       (btCOps(pCur)->Next(pCur, pRes))
-#define sqliteBtreePrevious(pCur, pRes)   (btCOps(pCur)->Previous(pCur, pRes))
-#define sqliteBtreeKeySize(pCur, pSize)   (btCOps(pCur)->KeySize(pCur, pSize) )
-#define sqliteBtreeKey(pCur, offset, amt, zBuf)\
-                (btCOps(pCur)->Key(pCur, offset, amt, zBuf))
-#define sqliteBtreeKeyCompare(pCur, pKey, nKey, nIgnore, pRes)\
-                (btCOps(pCur)->KeyCompare(pCur, pKey, nKey, nIgnore, pRes))
-#define sqliteBtreeDataSize(pCur, pSize)  (btCOps(pCur)->DataSize(pCur, pSize))
-#define sqliteBtreeData(pCur, offset, amt, zBuf)\
-                (btCOps(pCur)->Data(pCur, offset, amt, zBuf))
-#define sqliteBtreeCloseCursor(pCur)      (btCOps(pCur)->CloseCursor(pCur))
-#define sqliteBtreeGetMeta(pBt, aMeta)    (btOps(pBt)->GetMeta(pBt, aMeta))
-#define sqliteBtreeUpdateMeta(pBt, aMeta) (btOps(pBt)->UpdateMeta(pBt, aMeta))
-#define sqliteBtreeIntegrityCheck(pBt, aRoot, nRoot)\
-                (btOps(pBt)->IntegrityCheck(pBt, aRoot, nRoot))
-#define sqliteBtreeGetFilename(pBt)       (btOps(pBt)->GetFilename(pBt))
-#define sqliteBtreeCopyFile(pBt1, pBt2)   (btOps(pBt1)->Copyfile(pBt1, pBt2))
-#define sqliteBtreePager(pBt)             (btOps(pBt)->Pager(pBt))
+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 */
+);
 
-#ifdef SQLITE_TEST
-#define sqliteBtreePageDump(pBt, pgno, recursive)\
-                (btOps(pBt)->PageDump(pBt, pgno, recursive))
-#define sqliteBtreeCursorDump(pCur, aResult)\
-                (btCOps(pCur)->CursorDump(pCur, aResult))
-int btree_native_byte_order;
-#endif /* SQLITE_TEST */
+int sqlite3BtreeCursorClose(BtCursor*);
+int sqlite3BtreeMoveto(BtCursor*, const void *pKey, u64 nKey, int *pRes);
+int sqlite3BtreeDelete(BtCursor*);
+int sqlite3BtreeInsert(BtCursor*, const void *pKey, u64 nKey,
+                                  const void *pData, int nData);
+int sqlite3BtreeFirst(BtCursor*, int *pRes);
+int sqlite3BtreeLast(BtCursor*, int *pRes);
+int sqlite3BtreeNext(BtCursor*, int *pRes);
+int sqlite3BtreePrevious(BtCursor*, int *pRes);
+int sqlite3BtreeKeySize(BtCursor*, u64 *pSize);
+int sqlite3BtreeKey(BtCursor*, u32 offset, u32 amt, void*);
+void *sqlite3BtreeKeyFetch(BtCursor*);
+int sqlite3BtreeDataSize(BtCursor*, u32 *pSize);
+int sqlite3BtreeData(BtCursor*, u32 offset, u32 amt, void*);
 
 
 #endif /* _BTREE_H_ */
index a22f6d2dd6513f409e0e1bdb0cbdcb853efca640..4a4c49fe9b6177964557f347e1d0fd836a88a1f0 100644 (file)
--- a/src/md5.c
+++ b/src/md5.c
@@ -352,6 +352,7 @@ int Md5_Init(Tcl_Interp *interp){
   return TCL_OK;
 }
 
+#if 0
 /*
 ** During testing, the special md5sum() aggregate function is available.
 ** inside SQLite.  The following routines implement that function.
@@ -383,3 +384,4 @@ static void md5finalize(sqlite_func *context){
 void Md5_Register(sqlite *db){
   sqlite_create_aggregate(db, "md5sum", -1, md5step, md5finalize, 0);
 }
+#endif
index 8b6a154656b2330e0cb5cf8317a52c5b416fa527..41db493e779031ec1ed4ad4919c1c8581cc99ad0 100644 (file)
@@ -18,7 +18,7 @@
 ** file simultaneously, or one process from reading the database while
 ** another is writing.
 **
-** @(#) $Id: pager.c,v 1.101 2004/02/25 02:20:41 drh Exp $
+** @(#) $Id: pager.c,v 1.102 2004/04/26 14:10:21 drh Exp $
 */
 #include "os.h"         /* Must be first to enable large file support */
 #include "sqliteInt.h"
@@ -85,8 +85,8 @@ static Pager *mainPager = 0;
 ** This header is only visible to this pager module.  The client
 ** code that calls pager sees only the data that follows the header.
 **
-** Client code should call sqlitepager_write() on a page prior to making
-** any modifications to that page.  The first time sqlitepager_write()
+** Client code should call sqlite3pager_write() on a page prior to making
+** any modifications to that page.  The first time sqlite3pager_write()
 ** is called, the original page contents are written into the rollback
 ** journal and PgHdr.inJournal and PgHdr.needSync are set.  Later, once
 ** the journal page has made it onto the disk surface, PgHdr.needSync
@@ -94,7 +94,7 @@ static Pager *mainPager = 0;
 ** database file until the journal pages has been synced to disk and the
 ** PgHdr.needSync has been cleared.
 **
-** The PgHdr.dirty flag is set when sqlitepager_write() is called and
+** The PgHdr.dirty flag is set when sqlite3pager_write() is called and
 ** is cleared again when the page content is written back to the original
 ** database file.
 */
@@ -288,10 +288,10 @@ int journal_format = 3;
 ** Enable reference count tracking here:
 */
 #ifdef SQLITE_TEST
-  int pager_refinfo_enable = 0;
+  int pager3_refinfo_enable = 0;
   static void pager_refinfo(PgHdr *p){
     static int cnt = 0;
-    if( !pager_refinfo_enable ) return;
+    if( !pager3_refinfo_enable ) return;
     printf(
        "REFCNT: %4d addr=0x%08x nRef=%d\n",
        p->pgno, (int)PGHDR_TO_DATA(p), p->nRef
@@ -386,11 +386,11 @@ static int pager_errcode(Pager *pPager){
 ** checkpoint journal.
 **
 ** The Pager keeps a separate list of pages that are currently in
-** the checkpoint journal.  This helps the sqlitepager_ckpt_commit()
+** the checkpoint journal.  This helps the sqlite3pager_stmt_commit()
 ** routine run MUCH faster for the common case where there are many
 ** pages in memory but only a few are in the checkpoint journal.
 */
-static void page_add_to_ckpt_list(PgHdr *pPg){
+static void page_add_to_stmt_list(PgHdr *pPg){
   Pager *pPager = pPg->pPager;
   if( pPg->inCkpt ) return;
   assert( pPg->pPrevCkpt==0 && pPg->pNextCkpt==0 );
@@ -402,7 +402,7 @@ static void page_add_to_ckpt_list(PgHdr *pPg){
   pPager->pCkpt = pPg;
   pPg->inCkpt = 1;
 }
-static void page_remove_from_ckpt_list(PgHdr *pPg){
+static void page_remove_from_stmt_list(PgHdr *pPg){
   if( !pPg->inCkpt ) return;
   if( pPg->pPrevCkpt ){
     assert( pPg->pPrevCkpt->pNextCkpt==pPg );
@@ -451,7 +451,7 @@ static void pager_reset(Pager *pPager){
   memset(pPager->aHash, 0, sizeof(pPager->aHash));
   pPager->nPage = 0;
   if( pPager->state>=SQLITE_WRITELOCK ){
-    sqlitepager_rollback(pPager);
+    sqlite3pager_rollback(pPager);
   }
   sqliteOsUnlock(&pPager->fd);
   pPager->state = SQLITE_UNLOCK;
@@ -474,7 +474,7 @@ static int pager_unwritelock(Pager *pPager){
   int rc;
   PgHdr *pPg;
   if( pPager->state<SQLITE_WRITELOCK ) return SQLITE_OK;
-  sqlitepager_ckpt_commit(pPager);
+  sqlite3pager_stmt_commit(pPager);
   if( pPager->ckptOpen ){
     sqliteOsClose(&pPager->cpfd);
     pPager->ckptOpen = 0;
@@ -772,7 +772,7 @@ end_playback:
 **         playback all pages of the transaction journal beginning
 **         at offset pPager->ckptJSize.
 */
-static int pager_ckpt_playback(Pager *pPager){
+static int pager_stmt_playback(Pager *pPager){
   off_t szJ;               /* Size of the full journal */
   int nRec;                /* Number of Records */
   int i;                   /* Loop counter */
@@ -797,7 +797,7 @@ static int pager_ckpt_playback(Pager *pPager){
   for(i=nRec-1; i>=0; i--){
     rc = pager_playback_one_page(pPager, &pPager->cpfd, 2);
     assert( rc!=SQLITE_DONE );
-    if( rc!=SQLITE_OK ) goto end_ckpt_playback;
+    if( rc!=SQLITE_OK ) goto end_stmt_playback;
   }
 
   /* Figure out how many pages need to be copied out of the transaction
@@ -805,22 +805,22 @@ static int pager_ckpt_playback(Pager *pPager){
   */
   rc = sqliteOsSeek(&pPager->jfd, pPager->ckptJSize);
   if( rc!=SQLITE_OK ){
-    goto end_ckpt_playback;
+    goto end_stmt_playback;
   }
   rc = sqliteOsFileSize(&pPager->jfd, &szJ);
   if( rc!=SQLITE_OK ){
-    goto end_ckpt_playback;
+    goto end_stmt_playback;
   }
   nRec = (szJ - pPager->ckptJSize)/JOURNAL_PG_SZ(journal_format);
   for(i=nRec-1; i>=0; i--){
     rc = pager_playback_one_page(pPager, &pPager->jfd, journal_format);
     if( rc!=SQLITE_OK ){
       assert( rc!=SQLITE_DONE );
-      goto end_ckpt_playback;
+      goto end_stmt_playback;
     }
   }
   
-end_ckpt_playback:
+end_stmt_playback:
   if( rc!=SQLITE_OK ){
     pPager->errMask |= PAGER_ERR_CORRUPT;
     rc = SQLITE_CORRUPT;
@@ -838,7 +838,7 @@ end_ckpt_playback:
 ** failure, the database file might be left in an inconsistent and
 ** unrepairable state.  
 */
-void sqlitepager_set_cachesize(Pager *pPager, int mxPage){
+void sqlite3pager_set_cachesize(Pager *pPager, int mxPage){
   if( mxPage>=0 ){
     pPager->noSync = pPager->tempFile;
     if( pPager->noSync==0 ) pPager->needSync = 0;
@@ -877,7 +877,7 @@ void sqlitepager_set_cachesize(Pager *pPager, int mxPage){
 ** Numeric values associated with these states are OFF==1, NORMAL=2,
 ** and FULL=3.
 */
-void sqlitepager_set_safety_level(Pager *pPager, int level){
+void sqlite3pager_set_safety_level(Pager *pPager, int level){
   pPager->noSync =  level==1 || pPager->tempFile;
   pPager->fullSync = level==3 && !pPager->tempFile;
   if( pPager->noSync==0 ) pPager->needSync = 0;
@@ -892,7 +892,7 @@ void sqlitepager_set_safety_level(Pager *pPager, int level){
 ** The OS will automatically delete the temporary file when it is
 ** closed.
 */
-static int sqlitepager_opentemp(char *zFile, OsFile *fd){
+static int sqlite3pager_opentemp(char *zFile, OsFile *fd){
   int cnt = 8;
   int rc;
   do{
@@ -906,14 +906,14 @@ static int sqlitepager_opentemp(char *zFile, OsFile *fd){
 /*
 ** Create a new page cache and put a pointer to the page cache in *ppPager.
 ** The file to be cached need not exist.  The file is not locked until
-** the first call to sqlitepager_get() and is only held open until the
-** last page is released using sqlitepager_unref().
+** the first call to sqlite3pager_get() and is only held open until the
+** last page is released using sqlite3pager_unref().
 **
 ** If zFilename is NULL then a randomly-named temporary file is created
 ** and used as the file to be cached.  The file will be deleted
 ** automatically when it is closed.
 */
-int sqlitepager_open(
+int sqlite3pager_open(
   Pager **ppPager,         /* Return the Pager structure here */
   const char *zFilename,   /* Name of the database file to open */
   int mxPage,              /* Max number of in-memory cache pages */
@@ -938,7 +938,7 @@ int sqlitepager_open(
     rc = sqliteOsOpenReadWrite(zFullPathname, &fd, &readOnly);
     tempFile = 0;
   }else{
-    rc = sqlitepager_opentemp(zTemp, &fd);
+    rc = sqlite3pager_opentemp(zTemp, &fd);
     zFilename = zTemp;
     zFullPathname = sqliteOsFullPathname(zFilename);
     tempFile = 1;
@@ -999,10 +999,10 @@ int sqlitepager_open(
 ** when the reference count on each page reaches zero.  The destructor can
 ** be used to clean up information in the extra segment appended to each page.
 **
-** The destructor is not called as a result sqlitepager_close().  
-** Destructors are only called by sqlitepager_unref().
+** The destructor is not called as a result sqlite3pager_close().  
+** Destructors are only called by sqlite3pager_unref().
 */
-void sqlitepager_set_destructor(Pager *pPager, void (*xDesc)(void*)){
+void sqlite3pager_set_destructor(Pager *pPager, void (*xDesc)(void*)){
   pPager->xDestructor = xDesc;
 }
 
@@ -1010,7 +1010,7 @@ void sqlitepager_set_destructor(Pager *pPager, void (*xDesc)(void*)){
 ** Return the total number of pages in the disk file associated with
 ** pPager.
 */
-int sqlitepager_pagecount(Pager *pPager){
+int sqlite3pager_pagecount(Pager *pPager){
   off_t n;
   assert( pPager!=0 );
   if( pPager->dbSize>=0 ){
@@ -1035,10 +1035,10 @@ static int syncJournal(Pager*);
 /*
 ** Truncate the file to the number of pages specified.
 */
-int sqlitepager_truncate(Pager *pPager, Pgno nPage){
+int sqlite3pager_truncate(Pager *pPager, Pgno nPage){
   int rc;
   if( pPager->dbSize<0 ){
-    sqlitepager_pagecount(pPager);
+    sqlite3pager_pagecount(pPager);
   }
   if( pPager->errMask!=0 ){
     rc = pager_errcode(pPager);
@@ -1064,11 +1064,11 @@ int sqlitepager_truncate(Pager *pPager, Pgno nPage){
 ** with this page cache after this function returns will likely
 ** result in a coredump.
 */
-int sqlitepager_close(Pager *pPager){
+int sqlite3pager_close(Pager *pPager){
   PgHdr *pPg, *pNext;
   switch( pPager->state ){
     case SQLITE_WRITELOCK: {
-      sqlitepager_rollback(pPager);
+      sqlite3pager_rollback(pPager);
       sqliteOsUnlock(&pPager->fd);
       assert( pPager->journalOpen==0 );
       break;
@@ -1107,7 +1107,7 @@ int sqlitepager_close(Pager *pPager){
 /*
 ** Return the page number for the given page data.
 */
-Pgno sqlitepager_pagenumber(void *pData){
+Pgno sqlite3pager_pagenumber(void *pData){
   PgHdr *p = DATA_TO_PGHDR(pData);
   return p->pgno;
 }
@@ -1146,7 +1146,7 @@ static void _page_ref(PgHdr *pPg){
 ** Increment the reference count for a page.  The input pointer is
 ** a reference to the page data.
 */
-int sqlitepager_ref(void *pData){
+int sqlite3pager_ref(void *pData){
   PgHdr *pPg = DATA_TO_PGHDR(pData);
   page_ref(pPg);
   return SQLITE_OK;
@@ -1300,7 +1300,7 @@ static PgHdr *pager_get_all_dirty_pages(Pager *pPager){
 ** The acquisition might fail for several reasons.  In all cases,
 ** an appropriate error code is returned and *ppPage is set to NULL.
 **
-** See also sqlitepager_lookup().  Both this routine and _lookup() attempt
+** See also sqlite3pager_lookup().  Both this routine and _lookup() attempt
 ** to find a page in the in-memory cache first.  If the page is not already
 ** in memory, this routine goes to disk to read it in whereas _lookup()
 ** just returns 0.  This routine acquires a read-lock the first time it
@@ -1308,7 +1308,7 @@ static PgHdr *pager_get_all_dirty_pages(Pager *pPager){
 ** Since _lookup() never goes to disk, it never has to deal with locks
 ** or journal files.
 */
-int sqlitepager_get(Pager *pPager, Pgno pgno, void **ppPage){
+int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){
   PgHdr *pPg;
   int rc;
 
@@ -1414,7 +1414,7 @@ int sqlitepager_get(Pager *pPager, Pgno pgno, void **ppPage){
       if( pPg==0 ){
         int rc = syncJournal(pPager);
         if( rc!=0 ){
-          sqlitepager_rollback(pPager);
+          sqlite3pager_rollback(pPager);
           return SQLITE_IOERR;
         }
         pPg = pPager->pFirst;
@@ -1428,7 +1428,7 @@ int sqlitepager_get(Pager *pPager, Pgno pgno, void **ppPage){
         pPg->pDirty = 0;
         rc = pager_write_pagelist( pPg );
         if( rc!=SQLITE_OK ){
-          sqlitepager_rollback(pPager);
+          sqlite3pager_rollback(pPager);
           return SQLITE_IOERR;
         }
       }
@@ -1491,9 +1491,9 @@ int sqlitepager_get(Pager *pPager, Pgno pgno, void **ppPage){
     }
     if( pPager->aInCkpt && (int)pgno<=pPager->ckptSize
              && (pPager->aInCkpt[pgno/8] & (1<<(pgno&7)))!=0 ){
-      page_add_to_ckpt_list(pPg);
+      page_add_to_stmt_list(pPg);
     }else{
-      page_remove_from_ckpt_list(pPg);
+      page_remove_from_stmt_list(pPg);
     }
     pPg->dirty = 0;
     pPg->nRef = 1;
@@ -1509,9 +1509,9 @@ int sqlitepager_get(Pager *pPager, Pgno pgno, void **ppPage){
     if( pPager->nExtra>0 ){
       memset(PGHDR_TO_EXTRA(pPg), 0, pPager->nExtra);
     }
-    if( pPager->dbSize<0 ) sqlitepager_pagecount(pPager);
+    if( pPager->dbSize<0 ) sqlite3pager_pagecount(pPager);
     if( pPager->errMask!=0 ){
-      sqlitepager_unref(PGHDR_TO_DATA(pPg));
+      sqlite3pager_unref(PGHDR_TO_DATA(pPg));
       rc = pager_errcode(pPager);
       return rc;
     }
@@ -1527,7 +1527,7 @@ int sqlitepager_get(Pager *pPager, Pgno pgno, void **ppPage){
         off_t fileSize;
         if( sqliteOsFileSize(&pPager->fd,&fileSize)!=SQLITE_OK
                || fileSize>=pgno*SQLITE_PAGE_SIZE ){
-          sqlitepager_unref(PGHDR_TO_DATA(pPg));
+          sqlite3pager_unref(PGHDR_TO_DATA(pPg));
           return rc;
         }else{
           memset(PGHDR_TO_DATA(pPg), 0, SQLITE_PAGE_SIZE);
@@ -1548,13 +1548,13 @@ int sqlitepager_get(Pager *pPager, Pgno pgno, void **ppPage){
 ** not read the page from disk.  Return a pointer to the page,
 ** or 0 if the page is not in cache.
 **
-** See also sqlitepager_get().  The difference between this routine
-** and sqlitepager_get() is that _get() will go to the disk and read
+** See also sqlite3pager_get().  The difference between this routine
+** and sqlite3pager_get() is that _get() will go to the disk and read
 ** in the page if the page is not already in cache.  This routine
 ** returns NULL if the page is not in cache or if a disk I/O error 
 ** has ever happened.
 */
-void *sqlitepager_lookup(Pager *pPager, Pgno pgno){
+void *sqlite3pager_lookup(Pager *pPager, Pgno pgno){
   PgHdr *pPg;
 
   assert( pPager!=0 );
@@ -1580,7 +1580,7 @@ void *sqlitepager_lookup(Pager *pPager, Pgno pgno){
 ** are released, a rollback occurs and the lock on the database is
 ** removed.
 */
-int sqlitepager_unref(void *pData){
+int sqlite3pager_unref(void *pData){
   PgHdr *pPg;
 
   /* Decrement the reference count for this page
@@ -1635,7 +1635,7 @@ static int pager_open_journal(Pager *pPager){
   assert( pPager->state==SQLITE_WRITELOCK );
   assert( pPager->journalOpen==0 );
   assert( pPager->useJournal );
-  sqlitepager_pagecount(pPager);
+  sqlite3pager_pagecount(pPager);
   pPager->aInJournal = sqliteMalloc( pPager->dbSize/8 + 1 );
   if( pPager->aInJournal==0 ){
     sqliteOsReadLock(&pPager->fd);
@@ -1680,7 +1680,7 @@ static int pager_open_journal(Pager *pPager){
     rc = write32bits(&pPager->jfd, pPager->dbSize);
   }
   if( pPager->ckptAutoopen && rc==SQLITE_OK ){
-    rc = sqlitepager_ckpt_begin(pPager);
+    rc = sqlite3pager_stmt_begin(pPager);
   }
   if( rc!=SQLITE_OK ){
     rc = pager_unwritelock(pPager);
@@ -1695,10 +1695,10 @@ static int pager_open_journal(Pager *pPager){
 ** Acquire a write-lock on the database.  The lock is removed when
 ** the any of the following happen:
 **
-**   *  sqlitepager_commit() is called.
-**   *  sqlitepager_rollback() is called.
-**   *  sqlitepager_close() is called.
-**   *  sqlitepager_unref() is called to on every outstanding page.
+**   *  sqlite3pager_commit() is called.
+**   *  sqlite3pager_rollback() is called.
+**   *  sqlite3pager_close() is called.
+**   *  sqlite3pager_unref() is called to on every outstanding page.
 **
 ** The parameter to this routine is a pointer to any open page of the
 ** database file.  Nothing changes about the page - it is used merely
@@ -1711,7 +1711,7 @@ static int pager_open_journal(Pager *pPager){
 **
 ** If the database is already write-locked, this routine is a no-op.
 */
-int sqlitepager_begin(void *pData){
+int sqlite3pager_begin(void *pData){
   PgHdr *pPg = DATA_TO_PGHDR(pData);
   Pager *pPager = pPg->pPager;
   int rc = SQLITE_OK;
@@ -1747,10 +1747,10 @@ int sqlitepager_begin(void *pData){
 ** If the journal file could not be written because the disk is full,
 ** then this routine returns SQLITE_FULL and does an immediate rollback.
 ** All subsequent write attempts also return SQLITE_FULL until there
-** is a call to sqlitepager_commit() or sqlitepager_rollback() to
+** is a call to sqlite3pager_commit() or sqlite3pager_rollback() to
 ** reset.
 */
-int sqlitepager_write(void *pData){
+int sqlite3pager_write(void *pData){
   PgHdr *pPg = DATA_TO_PGHDR(pData);
   Pager *pPager = pPg->pPager;
   int rc = SQLITE_OK;
@@ -1781,7 +1781,7 @@ int sqlitepager_write(void *pData){
   ** create it if it does not.
   */
   assert( pPager->state!=SQLITE_UNLOCK );
-  rc = sqlitepager_begin(pData);
+  rc = sqlite3pager_begin(pData);
   if( rc!=SQLITE_OK ){
     return rc;
   }
@@ -1818,7 +1818,7 @@ int sqlitepager_write(void *pData){
         *(u32*)PGHDR_TO_EXTRA(pPg) = saved;
       }
       if( rc!=SQLITE_OK ){
-        sqlitepager_rollback(pPager);
+        sqlite3pager_rollback(pPager);
         pPager->errMask |= PAGER_ERR_FULL;
         return rc;
       }
@@ -1829,7 +1829,7 @@ int sqlitepager_write(void *pData){
       pPg->inJournal = 1;
       if( pPager->ckptInUse ){
         pPager->aInCkpt[pPg->pgno/8] |= 1<<(pPg->pgno&7);
-        page_add_to_ckpt_list(pPg);
+        page_add_to_stmt_list(pPg);
       }
     }else{
       pPg->needSync = !pPager->journalStarted && !pPager->noSync;
@@ -1853,14 +1853,14 @@ int sqlitepager_write(void *pData){
     TRACE2("CKPT-JOURNAL %d\n", pPg->pgno);
     CODEC(pPager, pData, pPg->pgno, 0);
     if( rc!=SQLITE_OK ){
-      sqlitepager_rollback(pPager);
+      sqlite3pager_rollback(pPager);
       pPager->errMask |= PAGER_ERR_FULL;
       return rc;
     }
     pPager->ckptNRec++;
     assert( pPager->aInCkpt!=0 );
     pPager->aInCkpt[pPg->pgno/8] |= 1<<(pPg->pgno&7);
-    page_add_to_ckpt_list(pPg);
+    page_add_to_stmt_list(pPg);
   }
 
   /* Update the database size and return.
@@ -1873,10 +1873,10 @@ int sqlitepager_write(void *pData){
 
 /*
 ** Return TRUE if the page given in the argument was previously passed
-** to sqlitepager_write().  In other words, return TRUE if it is ok
+** to sqlite3pager_write().  In other words, return TRUE if it is ok
 ** to change the content of the page.
 */
-int sqlitepager_iswriteable(void *pData){
+int sqlite3pager_iswriteable(void *pData){
   PgHdr *pPg = DATA_TO_PGHDR(pData);
   return pPg->dirty;
 }
@@ -1885,17 +1885,17 @@ int sqlitepager_iswriteable(void *pData){
 ** Replace the content of a single page with the information in the third
 ** argument.
 */
-int sqlitepager_overwrite(Pager *pPager, Pgno pgno, void *pData){
+int sqlite3pager_overwrite(Pager *pPager, Pgno pgno, void *pData){
   void *pPage;
   int rc;
 
-  rc = sqlitepager_get(pPager, pgno, &pPage);
+  rc = sqlite3pager_get(pPager, pgno, &pPage);
   if( rc==SQLITE_OK ){
-    rc = sqlitepager_write(pPage);
+    rc = sqlite3pager_write(pPage);
     if( rc==SQLITE_OK ){
       memcpy(pPage, pData, SQLITE_PAGE_SIZE);
     }
-    sqlitepager_unref(pPage);
+    sqlite3pager_unref(pPage);
   }
   return rc;
 }
@@ -1910,11 +1910,11 @@ int sqlitepager_overwrite(Pager *pPager, Pgno pgno, void *pData){
 ** that it does not get written to disk.
 **
 ** Tests show that this optimization, together with the
-** sqlitepager_dont_rollback() below, more than double the speed
+** sqlite3pager_dont_rollback() below, more than double the speed
 ** of large INSERT operations and quadruple the speed of large DELETEs.
 **
 ** When this routine is called, set the alwaysRollback flag to true.
-** Subsequent calls to sqlitepager_dont_rollback() for the same page
+** Subsequent calls to sqlite3pager_dont_rollback() for the same page
 ** will thereafter be ignored.  This is necessary to avoid a problem
 ** where a page with data is added to the freelist during one part of
 ** a transaction then removed from the freelist during a later part
@@ -1924,7 +1924,7 @@ int sqlitepager_overwrite(Pager *pPager, Pgno pgno, void *pData){
 ** critical data, we still need to be sure it gets rolled back in spite
 ** of the dont_rollback() call.
 */
-void sqlitepager_dont_write(Pager *pPager, Pgno pgno){
+void sqlite3pager_dont_write(Pager *pPager, Pgno pgno){
   PgHdr *pPg;
 
   pPg = pager_lookup(pPager, pgno);
@@ -1952,7 +1952,7 @@ void sqlitepager_dont_write(Pager *pPager, Pgno pgno){
 ** means that the pager does not have to record the given page in the
 ** rollback journal.
 */
-void sqlitepager_dont_rollback(void *pData){
+void sqlite3pager_dont_rollback(void *pData){
   PgHdr *pPg = DATA_TO_PGHDR(pData);
   Pager *pPager = pPg->pPager;
 
@@ -1964,7 +1964,7 @@ void sqlitepager_dont_rollback(void *pData){
     pPg->inJournal = 1;
     if( pPager->ckptInUse ){
       pPager->aInCkpt[pPg->pgno/8] |= 1<<(pPg->pgno&7);
-      page_add_to_ckpt_list(pPg);
+      page_add_to_stmt_list(pPg);
     }
     TRACE2("DONT_ROLLBACK %d\n", pPg->pgno);
   }
@@ -1972,7 +1972,7 @@ void sqlitepager_dont_rollback(void *pData){
     assert( pPg->inJournal || (int)pPg->pgno>pPager->origDbSize );
     assert( pPager->aInCkpt!=0 );
     pPager->aInCkpt[pPg->pgno/8] |= 1<<(pPg->pgno&7);
-    page_add_to_ckpt_list(pPg);
+    page_add_to_stmt_list(pPg);
   }
 }
 
@@ -1983,12 +1983,12 @@ void sqlitepager_dont_rollback(void *pData){
 ** and an error code is returned.  If the commit worked, SQLITE_OK
 ** is returned.
 */
-int sqlitepager_commit(Pager *pPager){
+int sqlite3pager_commit(Pager *pPager){
   int rc;
   PgHdr *pPg;
 
   if( pPager->errMask==PAGER_ERR_FULL ){
-    rc = sqlitepager_rollback(pPager);
+    rc = sqlite3pager_rollback(pPager);
     if( rc==SQLITE_OK ){
       rc = SQLITE_FULL;
     }
@@ -2029,7 +2029,7 @@ int sqlitepager_commit(Pager *pPager){
   /* Jump here if anything goes wrong during the commit process.
   */
 commit_abort:
-  rc = sqlitepager_rollback(pPager);
+  rc = sqlite3pager_rollback(pPager);
   if( rc==SQLITE_OK ){
     rc = SQLITE_FULL;
   }
@@ -2048,7 +2048,7 @@ commit_abort:
 ** codes are returned for all these occasions.  Otherwise,
 ** SQLITE_OK is returned.
 */
-int sqlitepager_rollback(Pager *pPager){
+int sqlite3pager_rollback(Pager *pPager){
   int rc;
   TRACE1("ROLLBACK\n");
   if( !pPager->dirtyFile || !pPager->journalOpen ){
@@ -2079,14 +2079,14 @@ int sqlitepager_rollback(Pager *pPager){
 ** Return TRUE if the database file is opened read-only.  Return FALSE
 ** if the database is (in theory) writable.
 */
-int sqlitepager_isreadonly(Pager *pPager){
+int sqlite3pager_isreadonly(Pager *pPager){
   return pPager->readOnly;
 }
 
 /*
 ** This routine is used for testing and analysis only.
 */
-int *sqlitepager_stats(Pager *pPager){
+int *sqlite3pager_stats(Pager *pPager){
   static int a[9];
   a[0] = pPager->nRef;
   a[1] = pPager->nPage;
@@ -2107,7 +2107,7 @@ int *sqlitepager_stats(Pager *pPager){
 ** open.  A new checkpoint journal is created that can be used to rollback
 ** changes of a single SQL command within a larger transaction.
 */
-int sqlitepager_ckpt_begin(Pager *pPager){
+int sqlite3pager_stmt_begin(Pager *pPager){
   int rc;
   char zTemp[SQLITE_TEMPNAME_SIZE];
   if( !pPager->journalOpen ){
@@ -2131,7 +2131,7 @@ int sqlitepager_ckpt_begin(Pager *pPager){
                          + JOURNAL_HDR_SZ(journal_format);
   pPager->ckptSize = pPager->dbSize;
   if( !pPager->ckptOpen ){
-    rc = sqlitepager_opentemp(zTemp, &pPager->cpfd);
+    rc = sqlite3pager_opentemp(zTemp, &pPager->cpfd);
     if( rc ) goto ckpt_begin_failed;
     pPager->ckptOpen = 1;
     pPager->ckptNRec = 0;
@@ -2150,7 +2150,7 @@ ckpt_begin_failed:
 /*
 ** Commit a checkpoint.
 */
-int sqlitepager_ckpt_commit(Pager *pPager){
+int sqlite3pager_stmt_commit(Pager *pPager){
   if( pPager->ckptInUse ){
     PgHdr *pPg, *pNext;
     sqliteOsSeek(&pPager->cpfd, 0);
@@ -2174,11 +2174,11 @@ int sqlitepager_ckpt_commit(Pager *pPager){
 /*
 ** Rollback a checkpoint.
 */
-int sqlitepager_ckpt_rollback(Pager *pPager){
+int sqlite3pager_stmt_rollback(Pager *pPager){
   int rc;
   if( pPager->ckptInUse ){
-    rc = pager_ckpt_playback(pPager);
-    sqlitepager_ckpt_commit(pPager);
+    rc = pager_stmt_playback(pPager);
+    sqlite3pager_stmt_commit(pPager);
   }else{
     rc = SQLITE_OK;
   }
@@ -2189,14 +2189,14 @@ int sqlitepager_ckpt_rollback(Pager *pPager){
 /*
 ** Return the full pathname of the database file.
 */
-const char *sqlitepager_filename(Pager *pPager){
+const char *sqlite3pager_filename(Pager *pPager){
   return pPager->zFilename;
 }
 
 /*
 ** Set the codec for this pager
 */
-void sqlitepager_set_codec(
+void sqlite3pager_set_codec(
   Pager *pPager,
   void (*xCodec)(void*,void*,Pgno,int),
   void *pCodecArg
@@ -2209,7 +2209,7 @@ void sqlitepager_set_codec(
 /*
 ** Print a listing of all referenced pages and their ref count.
 */
-void sqlitepager_refdump(Pager *pPager){
+void sqlite3pager_refdump(Pager *pPager){
   PgHdr *pPg;
   for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
     if( pPg->nRef<=0 ) continue;
index 09bc7aedec0399406310fb8d3849f24a8188a145..e506e042632f8b68080a5a38912861752267e0f3 100644 (file)
@@ -13,7 +13,7 @@
 ** subsystem.  The page cache subsystem reads and writes a file a page
 ** at a time and provides a journal for rollback.
 **
-** @(#) $Id: pager.h,v 1.26 2004/02/11 02:18:07 drh Exp $
+** @(#) $Id: pager.h,v 1.27 2004/04/26 14:10:22 drh Exp $
 */
 
 /*
@@ -50,8 +50,7 @@
 #define SQLITE_USABLE_SIZE (SQLITE_PAGE_SIZE-SQLITE_PAGE_RESERVE)
 
 /*
-** Maximum number of pages in one database.  (This is a limitation of
-** imposed by 4GB files size limits.)
+** Maximum number of pages in one database.
 */
 #define SQLITE_MAX_PAGE 1073741823
 
@@ -70,38 +69,37 @@ typedef struct Pager Pager;
 ** See source code comments for a detailed description of the following
 ** routines:
 */
-int sqlitepager_open(Pager **ppPager, const char *zFilename,
+int sqlite3pager_open(Pager **ppPager, const char *zFilename,
                      int nPage, int nExtra, int useJournal);
-void sqlitepager_set_destructor(Pager*, void(*)(void*));
-void sqlitepager_set_cachesize(Pager*, int);
-int sqlitepager_close(Pager *pPager);
-int sqlitepager_get(Pager *pPager, Pgno pgno, void **ppPage);
-void *sqlitepager_lookup(Pager *pPager, Pgno pgno);
-int sqlitepager_ref(void*);
-int sqlitepager_unref(void*);
-Pgno sqlitepager_pagenumber(void*);
-int sqlitepager_write(void*);
-int sqlitepager_iswriteable(void*);
-int sqlitepager_overwrite(Pager *pPager, Pgno pgno, void*);
-int sqlitepager_pagecount(Pager*);
-int sqlitepager_truncate(Pager*,Pgno);
-int sqlitepager_begin(void*);
-int sqlitepager_commit(Pager*);
-int sqlitepager_rollback(Pager*);
-int sqlitepager_isreadonly(Pager*);
-int sqlitepager_ckpt_begin(Pager*);
-int sqlitepager_ckpt_commit(Pager*);
-int sqlitepager_ckpt_rollback(Pager*);
-void sqlitepager_dont_rollback(void*);
-void sqlitepager_dont_write(Pager*, Pgno);
-int *sqlitepager_stats(Pager*);
-void sqlitepager_set_safety_level(Pager*,int);
-const char *sqlitepager_filename(Pager*);
-int sqlitepager_rename(Pager*, const char *zNewName);
-void sqlitepager_set_codec(Pager*,void(*)(void*,void*,Pgno,int),void*);
+void sqlite3pager_set_destructor(Pager*, void(*)(void*));
+void sqlite3pager_set_cachesize(Pager*, int);
+int sqlite3pager_close(Pager *pPager);
+int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage);
+void *sqlite3pager_lookup(Pager *pPager, Pgno pgno);
+int sqlite3pager_ref(void*);
+int sqlite3pager_unref(void*);
+Pgno sqlite3pager_pagenumber(void*);
+int sqlite3pager_write(void*);
+int sqlite3pager_iswriteable(void*);
+int sqlite3pager_overwrite(Pager *pPager, Pgno pgno, void*);
+int sqlite3pager_pagecount(Pager*);
+int sqlite3pager_truncate(Pager*,Pgno);
+int sqlite3pager_begin(void*);
+int sqlite3pager_commit(Pager*);
+int sqlite3pager_rollback(Pager*);
+int sqlite3pager_isreadonly(Pager*);
+int sqlite3pager_stmt_begin(Pager*);
+int sqlite3pager_stmt_commit(Pager*);
+int sqlite3pager_stmt_rollback(Pager*);
+void sqlite3pager_dont_rollback(void*);
+void sqlite3pager_dont_write(Pager*, Pgno);
+int *sqlite3pager_stats(Pager*);
+void sqlite3pager_set_safety_level(Pager*,int);
+const char *sqlite3pager_filename(Pager*);
+int sqlite3pager_rename(Pager*, const char *zNewName);
+void sqlite3pager_set_codec(Pager*,void(*)(void*,void*,Pgno,int),void*);
 
 #ifdef SQLITE_TEST
-void sqlitepager_refdump(Pager*);
-int pager_refinfo_enable;
-int journal_format;
+void sqlite3pager_refdump(Pager*);
+int pager3_refinfo_enable;
 #endif
index 4c2b6434005a3035e64473cdc0e50902961e8690..c3e3de6c07c17613ae6a58faa515b478faeeaad9 100644 (file)
 *************************************************************************
 ** Internal interface definitions for SQLite.
 **
-** @(#) $Id: sqliteInt.h,v 1.220 2004/02/25 13:47:33 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.221 2004/04/26 14:10:22 drh Exp $
 */
 #include "config.h"
 #include "sqlite.h"
 #include "hash.h"
 #include "parse.h"
-#include "btree.h"
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -96,6 +95,9 @@
 **
 **         cc '-DUINTPTR_TYPE=long long int' ...
 */
+#ifndef UINT64_TYPE
+# define UINT64_TYPE unsigned long long int
+#endif
 #ifndef UINT32_TYPE
 # define UINT32_TYPE unsigned int
 #endif
 #   define INTPTR_TYPE long long
 # endif
 #endif
+typedef UINT64_TYPE u64;           /* 8-byte unsigned integer */
 typedef UINT32_TYPE u32;           /* 4-byte unsigned integer */
 typedef UINT16_TYPE u16;           /* 2-byte unsigned integer */
 typedef UINT8_TYPE u8;             /* 1-byte unsigned integer */
@@ -126,6 +129,7 @@ typedef unsigned INTPTR_TYPE uptr; /* Big enough to hold a pointer */
 ** Defer sourcing vdbe.h until after the "u8" typedef is defined.
 */
 #include "vdbe.h"
+#include "btree.h"
 
 /*
 ** Most C compilers these days recognize "long double", don't they?
index 4e3976478a4ec4497561af7216ad26cdd1da3313..e1ca4837364ff9d8ecbb8d249694770b3c310c66 100644 (file)
@@ -11,7 +11,7 @@
 *************************************************************************
 ** A TCL Interface to SQLite
 **
-** $Id: tclsqlite.c,v 1.59 2004/02/25 22:51:06 rdc Exp $
+** $Id: tclsqlite.c,v 1.60 2004/04/26 14:10:22 drh Exp $
 */
 #ifndef NO_TCL     /* Omit this whole file if TCL is unavailable */
 
@@ -21,6 +21,7 @@
 #include <string.h>
 #include <assert.h>
 
+#if 0
 /*
 ** If TCL uses UTF-8 and SQLite is configured to use iso8859, then we
 ** have to do a translation when going between the two.  Set the 
@@ -1155,6 +1156,7 @@ int Sqlite_SafeInit(Tcl_Interp *interp){
 int Tclsqlite_SafeInit(Tcl_Interp *interp){
   return TCL_OK;
 }
+#endif
 
 #if 0
 /*
@@ -1199,7 +1201,7 @@ int TCLSH_MAIN(int argc, char **argv){
   Tcl_Interp *interp;
   Tcl_FindExecutable(argv[0]);
   interp = Tcl_CreateInterp();
-  Sqlite_Init(interp);
+  /* Sqlite_Init(interp); */
 #ifdef SQLITE_TEST
   {
     extern int Sqlitetest1_Init(Tcl_Interp*);
@@ -1207,10 +1209,10 @@ int TCLSH_MAIN(int argc, char **argv){
     extern int Sqlitetest3_Init(Tcl_Interp*);
     extern int Sqlitetest4_Init(Tcl_Interp*);
     extern int Md5_Init(Tcl_Interp*);
-    Sqlitetest1_Init(interp);
+    /* Sqlitetest1_Init(interp); */
     Sqlitetest2_Init(interp);
-    Sqlitetest3_Init(interp);
-    Sqlitetest4_Init(interp);
+    /* Sqlitetest3_Init(interp); */
+    /* Sqlitetest4_Init(interp); */
     Md5_Init(interp);
   }
 #endif
index 3fb198bf96e3544c6946ae3ef17323e33803551a..e7f6024d92cad563add2078e7631a83721dfb1be 100644 (file)
@@ -13,7 +13,7 @@
 ** is not included in the SQLite library.  It is used for automated
 ** testing of the SQLite library.
 **
-** $Id: test2.c,v 1.16 2004/02/10 01:54:28 drh Exp $
+** $Id: test2.c,v 1.17 2004/04/26 14:10:22 drh Exp $
 */
 #include "os.h"
 #include "sqliteInt.h"
@@ -76,7 +76,7 @@ static int pager_open(
     return TCL_ERROR;
   }
   if( Tcl_GetInt(interp, argv[2], &nPage) ) return TCL_ERROR;
-  rc = sqlitepager_open(&pPager, argv[1], nPage, 0, 1);
+  rc = sqlite3pager_open(&pPager, argv[1], nPage, 0, 1);
   if( rc!=SQLITE_OK ){
     Tcl_AppendResult(interp, errorName(rc), 0);
     return TCL_ERROR;
@@ -105,7 +105,7 @@ static int pager_close(
     return TCL_ERROR;
   }
   if( Tcl_GetInt(interp, argv[1], (int*)&pPager) ) return TCL_ERROR;
-  rc = sqlitepager_close(pPager);
+  rc = sqlite3pager_close(pPager);
   if( rc!=SQLITE_OK ){
     Tcl_AppendResult(interp, errorName(rc), 0);
     return TCL_ERROR;
@@ -132,7 +132,7 @@ static int pager_rollback(
     return TCL_ERROR;
   }
   if( Tcl_GetInt(interp, argv[1], (int*)&pPager) ) return TCL_ERROR;
-  rc = sqlitepager_rollback(pPager);
+  rc = sqlite3pager_rollback(pPager);
   if( rc!=SQLITE_OK ){
     Tcl_AppendResult(interp, errorName(rc), 0);
     return TCL_ERROR;
@@ -159,7 +159,7 @@ static int pager_commit(
     return TCL_ERROR;
   }
   if( Tcl_GetInt(interp, argv[1], (int*)&pPager) ) return TCL_ERROR;
-  rc = sqlitepager_commit(pPager);
+  rc = sqlite3pager_commit(pPager);
   if( rc!=SQLITE_OK ){
     Tcl_AppendResult(interp, errorName(rc), 0);
     return TCL_ERROR;
@@ -168,11 +168,11 @@ static int pager_commit(
 }
 
 /*
-** Usage:   pager_ckpt_begin ID
+** Usage:   pager_stmt_begin ID
 **
 ** Start a new checkpoint.
 */
-static int pager_ckpt_begin(
+static int pager_stmt_begin(
   void *NotUsed,
   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
   int argc,              /* Number of arguments */
@@ -186,7 +186,7 @@ static int pager_ckpt_begin(
     return TCL_ERROR;
   }
   if( Tcl_GetInt(interp, argv[1], (int*)&pPager) ) return TCL_ERROR;
-  rc = sqlitepager_ckpt_begin(pPager);
+  rc = sqlite3pager_stmt_begin(pPager);
   if( rc!=SQLITE_OK ){
     Tcl_AppendResult(interp, errorName(rc), 0);
     return TCL_ERROR;
@@ -195,11 +195,11 @@ static int pager_ckpt_begin(
 }
 
 /*
-** Usage:   pager_ckpt_rollback ID
+** Usage:   pager_stmt_rollback ID
 **
 ** Rollback changes to a checkpoint
 */
-static int pager_ckpt_rollback(
+static int pager_stmt_rollback(
   void *NotUsed,
   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
   int argc,              /* Number of arguments */
@@ -213,7 +213,7 @@ static int pager_ckpt_rollback(
     return TCL_ERROR;
   }
   if( Tcl_GetInt(interp, argv[1], (int*)&pPager) ) return TCL_ERROR;
-  rc = sqlitepager_ckpt_rollback(pPager);
+  rc = sqlite3pager_stmt_rollback(pPager);
   if( rc!=SQLITE_OK ){
     Tcl_AppendResult(interp, errorName(rc), 0);
     return TCL_ERROR;
@@ -222,11 +222,11 @@ static int pager_ckpt_rollback(
 }
 
 /*
-** Usage:   pager_ckpt_commit ID
+** Usage:   pager_stmt_commit ID
 **
 ** Commit changes to a checkpoint
 */
-static int pager_ckpt_commit(
+static int pager_stmt_commit(
   void *NotUsed,
   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
   int argc,              /* Number of arguments */
@@ -240,7 +240,7 @@ static int pager_ckpt_commit(
     return TCL_ERROR;
   }
   if( Tcl_GetInt(interp, argv[1], (int*)&pPager) ) return TCL_ERROR;
-  rc = sqlitepager_ckpt_commit(pPager);
+  rc = sqlite3pager_stmt_commit(pPager);
   if( rc!=SQLITE_OK ){
     Tcl_AppendResult(interp, errorName(rc), 0);
     return TCL_ERROR;
@@ -267,7 +267,7 @@ static int pager_stats(
     return TCL_ERROR;
   }
   if( Tcl_GetInt(interp, argv[1], (int*)&pPager) ) return TCL_ERROR;
-  a = sqlitepager_stats(pPager);
+  a = sqlite3pager_stats(pPager);
   for(i=0; i<9; i++){
     static char *zName[] = {
       "ref", "page", "max", "size", "state", "err",
@@ -300,7 +300,7 @@ static int pager_pagecount(
     return TCL_ERROR;
   }
   if( Tcl_GetInt(interp, argv[1], (int*)&pPager) ) return TCL_ERROR;
-  sprintf(zBuf,"%d",sqlitepager_pagecount(pPager));
+  sprintf(zBuf,"%d",sqlite3pager_pagecount(pPager));
   Tcl_AppendResult(interp, zBuf, 0);
   return TCL_OK;
 }
@@ -328,7 +328,7 @@ static int page_get(
   }
   if( Tcl_GetInt(interp, argv[1], (int*)&pPager) ) return TCL_ERROR;
   if( Tcl_GetInt(interp, argv[2], &pgno) ) return TCL_ERROR;
-  rc = sqlitepager_get(pPager, pgno, &pPage);
+  rc = sqlite3pager_get(pPager, pgno, &pPage);
   if( rc!=SQLITE_OK ){
     Tcl_AppendResult(interp, errorName(rc), 0);
     return TCL_ERROR;
@@ -361,7 +361,7 @@ static int page_lookup(
   }
   if( Tcl_GetInt(interp, argv[1], (int*)&pPager) ) return TCL_ERROR;
   if( Tcl_GetInt(interp, argv[2], &pgno) ) return TCL_ERROR;
-  pPage = sqlitepager_lookup(pPager, pgno);
+  pPage = sqlite3pager_lookup(pPager, pgno);
   if( pPage ){
     sprintf(zBuf,"0x%x",(int)pPage);
     Tcl_AppendResult(interp, zBuf, 0);
@@ -388,7 +388,7 @@ static int page_unref(
     return TCL_ERROR;
   }
   if( Tcl_GetInt(interp, argv[1], (int*)&pPage) ) return TCL_ERROR;
-  rc = sqlitepager_unref(pPage);
+  rc = sqlite3pager_unref(pPage);
   if( rc!=SQLITE_OK ){
     Tcl_AppendResult(interp, errorName(rc), 0);
     return TCL_ERROR;
@@ -439,7 +439,7 @@ static int page_number(
     return TCL_ERROR;
   }
   if( Tcl_GetInt(interp, argv[1], (int*)&pPage) ) return TCL_ERROR;
-  sprintf(zBuf, "%d", sqlitepager_pagenumber(pPage));
+  sprintf(zBuf, "%d", sqlite3pager_pagenumber(pPage));
   Tcl_AppendResult(interp, zBuf, 0);
   return TCL_OK;
 }
@@ -463,7 +463,7 @@ static int page_write(
     return TCL_ERROR;
   }
   if( Tcl_GetInt(interp, argv[1], (int*)&pPage) ) return TCL_ERROR;
-  rc = sqlitepager_write(pPage);
+  rc = sqlite3pager_write(pPage);
   if( rc!=SQLITE_OK ){
     Tcl_AppendResult(interp, errorName(rc), 0);
     return TCL_ERROR;
@@ -534,9 +534,9 @@ int Sqlitetest2_Init(Tcl_Interp *interp){
     { "pager_close",             (Tcl_CmdProc*)pager_close         },
     { "pager_commit",            (Tcl_CmdProc*)pager_commit        },
     { "pager_rollback",          (Tcl_CmdProc*)pager_rollback      },
-    { "pager_ckpt_begin",        (Tcl_CmdProc*)pager_ckpt_begin    },
-    { "pager_ckpt_commit",       (Tcl_CmdProc*)pager_ckpt_commit   },
-    { "pager_ckpt_rollback",     (Tcl_CmdProc*)pager_ckpt_rollback },
+    { "pager_stmt_begin",        (Tcl_CmdProc*)pager_stmt_begin    },
+    { "pager_stmt_commit",       (Tcl_CmdProc*)pager_stmt_commit   },
+    { "pager_stmt_rollback",     (Tcl_CmdProc*)pager_stmt_rollback },
     { "pager_stats",             (Tcl_CmdProc*)pager_stats         },
     { "pager_pagecount",         (Tcl_CmdProc*)pager_pagecount     },
     { "page_get",                (Tcl_CmdProc*)page_get            },
@@ -554,8 +554,11 @@ int Sqlitetest2_Init(Tcl_Interp *interp){
   Tcl_LinkVar(interp, "sqlite_io_error_pending",
      (char*)&sqlite_io_error_pending, TCL_LINK_INT);
 #ifdef SQLITE_TEST
-  Tcl_LinkVar(interp, "journal_format",
-     (char*)&journal_format, TCL_LINK_INT);
+  {
+    extern int journal_format;
+    Tcl_LinkVar(interp, "journal_format",
+       (char*)&journal_format, TCL_LINK_INT);
+  }
 #endif
   sprintf(zBuf, "%d", SQLITE_PAGE_SIZE);
   Tcl_SetVar(interp, "SQLITE_PAGE_SIZE", zBuf, TCL_GLOBAL_ONLY); 
index 16b3b46a05a7998068bfb5709e86c3c428df4a7a..1f1d5462b7451567a0f80d47dd398e804e90dec3 100644 (file)
@@ -14,7 +14,7 @@
 ** This file contains functions for allocating memory, comparing
 ** strings, and stuff like that.
 **
-** $Id: util.c,v 1.74 2004/02/22 17:49:34 drh Exp $
+** $Id: util.c,v 1.75 2004/04/26 14:10:22 drh Exp $
 */
 #include "sqliteInt.h"
 #include <stdarg.h>
@@ -405,6 +405,7 @@ void sqliteSetNString(char **pz, ...){
   va_end(ap);
 }
 
+#if 0
 /*
 ** Add an error message to pParse->zErrMsg and increment pParse->nErr.
 ** The following formatting characters are allowed:
@@ -423,6 +424,7 @@ void sqliteErrorMsg(Parse *pParse, const char *zFormat, ...){
   pParse->zErrMsg = sqliteVMPrintf(zFormat, ap);
   va_end(ap);
 }
+#endif
 
 /*
 ** Convert an SQL-style quoted string into a normal string by removing
index b76c48eed6e90616095fe06789cf194aa1ac32a2..81381245a822a606c6e5a83715d39c9d5ed4d35e 100644 (file)
@@ -11,7 +11,7 @@
 # This file implements regression tests for SQLite library.  The
 # focus of this script is page cache subsystem.
 #
-# $Id: pager.test,v 1.14 2004/02/25 02:20:42 drh Exp $
+# $Id: pager.test,v 1.15 2004/04/26 14:10:22 drh Exp $
 
 
 set testdir [file dirname $argv0]
@@ -305,7 +305,7 @@ for {set i 1} {$i<20} {incr i} {
       page_write $gx "Page-$j v$i"
       page_unref $gx
       if {$j==$i} {
-        pager_ckpt_begin $p1
+        pager_stmt_begin $p1
       }
     }
   } {}
@@ -346,12 +346,12 @@ for {set i 1} {$i<20} {incr i} {
       page_write $gx "Page-$j v$i"
       page_unref $gx
       if {$j==$i} {
-        pager_ckpt_begin $p1
+        pager_stmt_begin $p1
       }
     }
   } {}
   do_test pager-4.5.$i.7 {
-    pager_ckpt_rollback $p1
+    pager_stmt_rollback $p1
     for {set j 2} {$j<=20} {incr j} {
       set gx [page_get $p1 $j]
       set value [page_read $gx]
@@ -373,12 +373,12 @@ for {set i 1} {$i<20} {incr i} {
       page_write $gx "Page-$j v$i"
       page_unref $gx
       if {$j==$i} {
-        pager_ckpt_begin $p1
+        pager_stmt_begin $p1
       }
     }
   } {}
   do_test pager-4.5.$i.9 {
-    pager_ckpt_commit $p1
+    pager_stmt_commit $p1
     for {set j 2} {$j<=20} {incr j} {
       set gx [page_get $p1 $j]
       set value [page_read $gx]
@@ -406,6 +406,7 @@ do_test pager-4.99 {
 
 } ;# end if( not mem: and has pager_open command );
 
+if 0 {
 # Ticket #615: an assertion fault inside the pager.  It is a benign
 # fault, but we might as well test for it.
 #
@@ -418,6 +419,6 @@ do_test pager-5.1 {
     COMMIT;
   }
 } {}
-
+}
 
 finish_test
index d46dbb989354becf16c605244bc4ecfd4cf481d9..30603f47ca298d07c4eaeb575019bec17802f7d5 100644 (file)
@@ -11,8 +11,9 @@
 # This file implements some common TCL routines used for regression
 # testing the SQLite library
 #
-# $Id: tester.tcl,v 1.28 2004/02/14 01:39:50 drh Exp $
+# $Id: tester.tcl,v 1.29 2004/04/26 14:10:22 drh Exp $
 
+if 0 {
 # Make sure tclsqlite was compiled correctly.  Abort now with an
 # error message if not.
 #
@@ -62,6 +63,8 @@ sqlite db ./test.db
 if {[info exists ::SETUP_SQL]} {
   db eval $::SETUP_SQL
 }
+}
+proc db {args} {}
 
 # Abort early if this script has been run before.
 #
@@ -180,10 +183,12 @@ proc finalize_testing {} {
     puts "$nProb probabilistic tests also failed, but this does"
     puts "not necessarily indicate a malfunction."
   }
+  if 0 {
   if {$sqlite_open_file_count} {
     puts "$sqlite_open_file_count files were left open"
     incr nErr
   }
+  }
   exit [expr {$nErr>0}]
 }