/ Check-in [b31c4902]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:The BTree code compiles and links now, but it does not work yet. (CVS 226)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: b31c49021c260a67b7848bc077b75a7146e31c71
User & Date: drh 2001-06-22 19:15:00
Context
2001-06-23
11:36
Fix a bug in pager.c introduced in the previous delta. (CVS 227) check-in: f4df6664 user: drh tags: trunk
2001-06-22
19:15
The BTree code compiles and links now, but it does not work yet. (CVS 226) check-in: b31c4902 user: drh tags: trunk
2001-06-10
19:56
All BTree code is in place. Now we just have to make it work. (CVS 225) check-in: d4be4709 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to Makefile.in.

    43     43   
    44     44   # The library that programs using readline() must link against.
    45     45   #
    46     46   LIBREADLINE = @TARGET_READLINE_LIBS@
    47     47   
    48     48   # Object files for the SQLite library.
    49     49   #
    50         -LIBOBJ = build.o dbbe.o dbbegdbm.o dbbemem.o delete.o expr.o insert.o \
           50  +LIBOBJ = btree.o build.o dbbe.o dbbegdbm.o dbbemem.o delete.o expr.o insert.o \
    51     51            main.o pager.o parse.o printf.o random.o select.o table.o \
    52     52            tokenize.o update.o util.o vdbe.o where.o tclsqlite.o
    53     53   
    54     54   # All of the source code files.
    55     55   #
    56     56   SRC = \
           57  +  $(TOP)/src/btree.c \
    57     58     $(TOP)/src/build.c \
    58     59     $(TOP)/src/dbbe.c \
    59     60     $(TOP)/src/dbbe.h \
    60     61     $(TOP)/src/dbbegdbm.c \
    61     62     $(TOP)/src/dbbemem.c \
    62     63     $(TOP)/src/delete.c \
    63     64     $(TOP)/src/expr.c \
................................................................................
    80     81     $(TOP)/src/vdbe.h \
    81     82     $(TOP)/src/where.c
    82     83   
    83     84   # Source code to the test files.
    84     85   #
    85     86   TESTSRC = \
    86     87     $(TOP)/src/test1.c \
    87         -  $(TOP)/src/test2.c
           88  +  $(TOP)/src/test2.c \
           89  +  $(TOP)/src/test3.c
    88     90   
    89     91   # This is the default Makefile target.  The objects listed here
    90     92   # are what get build when you type just "make" with no arguments.
    91     93   #
    92     94   all:	sqlite.h libsqlite.a sqlite 
    93     95   
    94     96   # Generate the file "last_change" which contains the date of change
................................................................................
   113    115   	cp $(TOP)/tool/lempar.c .
   114    116   
   115    117   # Header files used by all library source files.
   116    118   #
   117    119   HDR = \
   118    120      sqlite.h  \
   119    121      $(TOP)/src/sqliteInt.h  \
          122  +   $(TOP)/src/btree.h \
   120    123      $(TOP)/src/dbbe.h  \
          124  +   $(TOP)/src/pager.h \
   121    125      $(TOP)/src/vdbe.h  \
   122    126      parse.h
   123    127   
          128  +btree.o:	$(TOP)/src/btree.c $(HDR)
          129  +	$(TCC) $(GDBM_FLAGS) -c $(TOP)/src/btree.c
          130  +
   124    131   build.o:	$(TOP)/src/build.c $(HDR)
   125    132   	$(TCC) $(GDBM_FLAGS) -c $(TOP)/src/build.c
   126    133   
   127    134   dbbe.o:	$(TOP)/src/dbbe.c $(HDR)
   128    135   	$(TCC) $(GDBM_FLAGS) -c $(TOP)/src/dbbe.c
   129    136   
   130    137   dbbegdbm.o:	$(TOP)/src/dbbegdbm.c $(HDR)
................................................................................
   197    204   
   198    205   tclsqlite:	$(TOP)/src/tclsqlite.c libsqlite.a
   199    206   	$(TCC) $(TCL_FLAGS) -DTCLSH=1 -o tclsqlite \
   200    207   		$(TOP)/src/tclsqlite.c libsqlite.a $(LIBGDBM) $(LIBTCL)
   201    208   
   202    209   testfixture:	$(TOP)/src/tclsqlite.c libsqlite.a $(TESTSRC)
   203    210   	$(TCC) $(TCL_FLAGS) -DTCLSH=1 -DSQLITE_TEST=1 -o testfixture \
   204         -		$(TESTSRC) $(TOP)/src/tclsqlite.c \
          211  +		$(TESTSRC) $(TOP)/src/tclsqlite.c $(TOP)/src/btree.c \
   205    212   		libsqlite.a $(LIBGDBM) $(LIBTCL)
   206    213   
   207    214   test:	testfixture sqlite
   208    215   	./testfixture $(TOP)/test/all.test
   209    216   
   210    217   sqlite.tar.gz:	
   211    218   	pwd=`pwd`; cd $(TOP)/..; tar czf $$pwd/sqlite.tar.gz sqlite

Changes to src/btree.c.

    17     17   ** Boston, MA  02111-1307, USA.
    18     18   **
    19     19   ** Author contact information:
    20     20   **   drh@hwaci.com
    21     21   **   http://www.hwaci.com/drh/
    22     22   **
    23     23   *************************************************************************
    24         -** $Id: btree.c,v 1.12 2001/06/10 19:56:59 drh Exp $
           24  +** $Id: btree.c,v 1.13 2001/06/22 19:15:00 drh Exp $
    25     25   **
    26     26   ** This file implements a external (disk-based) database using BTrees.
    27     27   ** For a detailed discussion of BTrees, refer to
    28     28   **
    29     29   **     Donald E. Knuth, THE ART OF COMPUTER PROGRAMMING, Volume 3:
    30     30   **     "Sorting And Searching", pages 473-480. Addison-Wesley
    31     31   **     Publishing Company, Reading, Massachusetts.
................................................................................
    69     69   
    70     70   /*
    71     71   ** Primitive data types.  u32 must be 4 bytes and u16 must be 2 bytes.
    72     72   ** The uptr type must be big enough to hold a pointer.
    73     73   ** Change these typedefs when porting to new architectures.
    74     74   */
    75     75   typedef unsigned int uptr;
    76         -typedef unsigned int u32;
           76  +/*  typedef unsigned int u32; -- already defined in sqliteInt.h */
    77     77   typedef unsigned short int u16;
    78     78   typedef unsigned char u8;
    79     79   
           80  +/*
           81  +** This macro casts a pointer to an integer.  Useful for doing
           82  +** pointer arithmetic.
           83  +*/
           84  +#define addr(X)  ((uptr)X)
           85  +
    80     86   /*
    81     87   ** Forward declarations of structures used only in this file.
    82     88   */
    83     89   typedef struct PageOne PageOne;
    84     90   typedef struct MemPage MemPage;
    85     91   typedef struct PageHdr PageHdr;
    86     92   typedef struct Cell Cell;
................................................................................
    95    101   ** This might need to change for computer architectures that require
    96    102   ** and 8-byte alignment boundry for structures.
    97    103   */
    98    104   #define ROUNDUP(X)  ((X+3) & ~3)
    99    105   
   100    106   /*
   101    107   ** This is a magic string that appears at the beginning of every
   102         -** SQLite database in order to identify the fail as a real database.
          108  +** SQLite database in order to identify the file as a real database.
   103    109   */
   104    110   static const char zMagicHeader[] = 
   105         -   "** This file contains an SQLite 2.0 database **"
          111  +   "** This file contains an SQLite 2.0 database **";
   106    112   #define MAGIC_SIZE (sizeof(zMagicHeader))
   107    113   
          114  +/*
          115  +** This is a magic integer also used to the integrety of the database
          116  +** file.  This integer is used in addition to the string above so that
          117  +** if the file is written on a little-endian architecture and read
          118  +** on a big-endian architectures (or vice versa) we can detect the
          119  +** problem.
          120  +**
          121  +** The number used was obtained at random and has no special
          122  +** significance.
          123  +*/
          124  +#define MAGIC 0xdae37528
          125  +
   108    126   /*
   109    127   ** The first page of the database file contains a magic header string
   110    128   ** to identify the file as an SQLite database file.  It also contains
   111    129   ** a pointer to the first free page of the file.  Page 2 contains the
   112    130   ** root of the principle BTree.  The file might contain other BTrees
   113    131   ** rooted on pages above 2.
   114    132   **
................................................................................
   117    135   **
   118    136   ** Remember that pages are numbered beginning with 1.  (See pager.c
   119    137   ** for additional information.)  Page 0 does not exist and a page
   120    138   ** number of 0 is used to mean "no such page".
   121    139   */
   122    140   struct PageOne {
   123    141     char zMagic[MAGIC_SIZE]; /* String that identifies the file as a database */
   124         -  Pgno firstList;          /* First free page in a list of all free pages */
          142  +  int iMagic;              /* Integer to verify correct byte order */
          143  +  Pgno freeList;           /* First free page in a list of all free pages */
   125    144     int aMeta[SQLITE_N_BTREE_META];  /* User defined integers */
   126    145   };
   127    146   
   128    147   /*
   129    148   ** Each database page has a header that is an instance of this
   130    149   ** structure.
   131    150   **
................................................................................
   152    171   /*
   153    172   ** Entries on a page of the database are called "Cells".  Each Cell
   154    173   ** has a header and data.  This structure defines the header.  The
   155    174   ** key and data (collectively the "payload") follow this header on
   156    175   ** the database page.
   157    176   **
   158    177   ** A definition of the complete Cell structure is given below.  The
   159         -** header for the cell must be defined separately in order to do some
          178  +** header for the cell must be defined first in order to do some
   160    179   ** of the sizing #defines that follow.
   161    180   */
   162    181   struct CellHdr {
   163    182     Pgno leftChild; /* Child page that comes before this cell */
   164    183     u16 nKey;       /* Number of bytes in the key */
   165    184     u16 iNext;      /* Index in MemPage.u.aDisk[] of next cell in sorted order */
   166    185     u32 nData;      /* Number of bytes of data */
   167         -}
          186  +};
   168    187   
   169    188   /*
   170    189   ** The minimum size of a complete Cell.  The Cell must contain a header
   171    190   ** and at least 4 bytes of payload.
   172    191   */
   173    192   #define MIN_CELL_SIZE  (sizeof(CellHdr)+4)
   174    193   
................................................................................
   175    194   /*
   176    195   ** The maximum number of database entries that can be held in a single
   177    196   ** page of the database. 
   178    197   */
   179    198   #define MX_CELL ((SQLITE_PAGE_SIZE-sizeof(PageHdr))/MIN_CELL_SIZE)
   180    199   
   181    200   /*
   182         -** The maximum amount of data (in bytes) that can be stored locally for a
   183         -** database entry.  If the entry contains more data than this, the
          201  +** The maximum amount of payload (in bytes) that can be stored locally for
          202  +** a database entry.  If the entry contains more data than this, the
   184    203   ** extra goes onto overflow pages.
   185    204   **
   186    205   ** This number is chosen so that at least 4 cells will fit on every page.
   187    206   */
   188    207   #define MX_LOCAL_PAYLOAD \
   189    208     ((SQLITE_PAGE_SIZE-sizeof(PageHdr))/4-(sizeof(CellHdr)+sizeof(Pgno)))
   190    209   
................................................................................
   222    241   /*
   223    242   ** The number of bytes of payload that will fit on a single overflow page.
   224    243   */
   225    244   #define OVERFLOW_SIZE (SQLITE_PAGE_SIZE-sizeof(Pgno))
   226    245   
   227    246   /*
   228    247   ** When the key and data for a single entry in the BTree will not fit in
   229         -** the MX_LOACAL_PAYLOAD bytes of space available on the database page,
          248  +** the MX_LOCAL_PAYLOAD bytes of space available on the database page,
   230    249   ** then all extra bytes are written to a linked list of overflow pages.
   231    250   ** Each overflow page is an instance of the following structure.
   232    251   **
   233    252   ** Unused pages in the database are also represented by instances of
   234    253   ** the OverflowPage structure.  The PageOne.freeList field is the
   235    254   ** page number of the first page in a linked list of unused database
   236    255   ** pages.
................................................................................
   274    293     } u;
   275    294     int isInit;                    /* True if auxiliary data is initialized */
   276    295     MemPage *pParent;              /* The parent of this page.  NULL for root */
   277    296     int nFree;                     /* Number of free bytes in u.aDisk[] */
   278    297     int nCell;                     /* Number of entries on this page */
   279    298     int isOverfull;                /* Some apCell[] points outside u.aDisk[] */
   280    299     Cell *apCell[MX_CELL+2];       /* All data entires in sorted order */
   281         -}
          300  +};
   282    301   
   283    302   /*
   284    303   ** The in-memory image of a disk page has the auxiliary information appended
   285    304   ** to the end.  EXTRA_SIZE is the number of bytes of space needed to hold
   286    305   ** that extra information.
   287    306   */
   288    307   #define EXTRA_SIZE (sizeof(MemPage)-SQLITE_PAGE_SIZE)
................................................................................
   304    323   ** MemPage.apCell[] of the entry.
   305    324   */
   306    325   struct BtCursor {
   307    326     Btree *pBt;               /* The Btree to which this cursor belongs */
   308    327     BtCursor *pNext, *pPrev;  /* Forms a linked list of all cursors */
   309    328     Pgno pgnoRoot;            /* The root page of this tree */
   310    329     MemPage *pPage;           /* Page that contains the entry */
   311         -  u16 idx;                  /* Index of the entry in pPage->apCell[] */
          330  +  int idx;                  /* Index of the entry in pPage->apCell[] */
   312    331     u8 bSkipNext;             /* sqliteBtreeNext() is no-op if true */
   313    332     u8 iMatch;                /* compare result from last sqliteBtreeMoveto() */
   314    333   };
   315    334   
   316    335   /*
   317    336   ** Compute the total number of bytes that a Cell needs on the main
   318    337   ** database page.  The number returned includes the Cell header,
   319    338   ** local payload storage, and the pointer to overflow pages (if
   320         -** applicable).  Additional spaced allocated on overflow pages
          339  +** applicable).  Additional space allocated on overflow pages
   321    340   ** is NOT included in the value returned from this routine.
   322    341   */
   323    342   static int cellSize(Cell *pCell){
   324    343     int n = pCell->h.nKey + pCell->h.nData;
   325    344     if( n>MX_LOCAL_PAYLOAD ){
   326    345       n = MX_LOCAL_PAYLOAD + sizeof(Pgno);
   327    346     }else{
................................................................................
   341    360     FreeBlk *pFBlk;
   342    361     char newPage[SQLITE_PAGE_SIZE];
   343    362   
   344    363     pc = sizeof(PageHdr);
   345    364     pPage->u.hdr.firstCell = pc;
   346    365     memcpy(newPage, pPage->u.aDisk, pc);
   347    366     for(i=0; i<pPage->nCell; i++){
   348         -    Cell *pCell = &pPage->apCell[i];
          367  +    Cell *pCell = (Cell*)&pPage->apCell[i];
          368  +
          369  +    /* This routine should never be called on an overfull page.  The
          370  +    ** following asserts verify that constraint. */
          371  +    assert( addr(pCell) > addr(pPage) );
          372  +    assert( addr(pCell) < addr(pPage) + SQLITE_PAGE_SIZE );
          373  +
   349    374       n = cellSize(pCell);
   350    375       pCell->h.iNext = i<pPage->nCell-1 ? pc + n : 0;
   351    376       memcpy(&newPage[pc], pCell, n);
   352    377       pPage->apCell[i] = (Cell*)&pPage->u.aDisk[pc];
   353    378       pc += n;
   354    379     }
   355    380     assert( pPage->nFree==SQLITE_PAGE_SIZE-pc );
   356    381     memcpy(pPage->u.aDisk, newPage, pc);
   357         -  pFBlk = &pPage->u.aDisk[pc];
          382  +  pFBlk = (FreeBlk*)&pPage->u.aDisk[pc];
   358    383     pFBlk->iSize = SQLITE_PAGE_SIZE - pc;
   359    384     pFBlk->iNext = 0;
   360    385     pPage->u.hdr.firstFree = pc;
   361    386     memset(&pFBlk[1], 0, SQLITE_PAGE_SIZE - pc - sizeof(FreeBlk));
   362    387   }
   363    388   
   364    389   /*
................................................................................
   374    399   ** calls defragementPage() to consolidate all free space before 
   375    400   ** allocating the new chunk.
   376    401   */
   377    402   static int allocateSpace(MemPage *pPage, int nByte){
   378    403     FreeBlk *p;
   379    404     u16 *pIdx;
   380    405     int start;
          406  +  int cnt = 0;
   381    407   
   382    408     assert( nByte==ROUNDUP(nByte) );
   383    409     if( pPage->nFree<nByte || pPage->isOverfull ) return 0;
   384    410     pIdx = &pPage->u.hdr.firstFree;
   385    411     p = (FreeBlk*)&pPage->u.aDisk[*pIdx];
   386    412     while( p->iSize<nByte ){
          413  +    assert( cnt++ < SQLITE_PAGE_SIZE/4 );
   387    414       if( p->iNext==0 ){
   388    415         defragmentPage(pPage);
   389    416         pIdx = &pPage->u.hdr.firstFree;
   390    417       }else{
   391    418         pIdx = &p->iNext;
   392    419       }
   393    420       p = (FreeBlk*)&pPage->u.aDisk[*pIdx];
   394    421     }
   395    422     if( p->iSize==nByte ){
   396    423       start = *pIdx;
   397    424       *pIdx = p->iNext;
   398    425     }else{
          426  +    FreeBlk *pNew;
   399    427       start = *pIdx;
   400         -    FreeBlk *pNew = (FreeBlk*)&pPage->u.aDisk[start + nByte];
          428  +    pNew = (FreeBlk*)&pPage->u.aDisk[start + nByte];
   401    429       pNew->iNext = p->iNext;
   402    430       pNew->iSize = p->iSize - nByte;
   403    431       *pIdx = start + nByte;
   404    432     }
   405    433     pPage->nFree -= nByte;
   406    434     return start;
   407    435   }
................................................................................
   427    455     pIdx = &pPage->u.hdr.firstFree;
   428    456     idx = *pIdx;
   429    457     while( idx!=0 && idx<start ){
   430    458       pFBlk = (FreeBlk*)&pPage->u.aDisk[idx];
   431    459       if( idx + pFBlk->iSize == start ){
   432    460         pFBlk->iSize += size;
   433    461         if( idx + pFBlk->iSize == pFBlk->iNext ){
   434         -        pNext = (FreeBlk*)&pPage->u.aDisk[pFblk->iNext];
          462  +        pNext = (FreeBlk*)&pPage->u.aDisk[pFBlk->iNext];
   435    463           pFBlk->iSize += pNext->iSize;
   436    464           pFBlk->iNext = pNext->iNext;
   437    465         }
   438    466         pPage->nFree += size;
   439    467         return;
   440    468       }
   441    469       pIdx = &pFBlk->iNext;
................................................................................
   485    513     }
   486    514     if( pPage->isInit ) return SQLITE_OK;
   487    515     pPage->isInit = 1;
   488    516     pPage->nCell = 0;
   489    517     freeSpace = SQLITE_PAGE_SIZE - sizeof(PageHdr);
   490    518     idx = pPage->u.hdr.firstCell;
   491    519     while( idx!=0 ){
   492         -    if( idx>SQLITE_PAGE_SIZE-MN_CELL_SIZE ) goto page_format_error;
          520  +    if( idx>SQLITE_PAGE_SIZE-MIN_CELL_SIZE ) goto page_format_error;
   493    521       if( idx<sizeof(PageHdr) ) goto page_format_error;
          522  +    if( idx!=ROUNDUP(idx) ) goto page_format_error;
   494    523       pCell = (Cell*)&pPage->u.aDisk[idx];
   495    524       sz = cellSize(pCell);
   496    525       if( idx+sz > SQLITE_PAGE_SIZE ) goto page_format_error;
   497    526       freeSpace -= sz;
   498    527       pPage->apCell[pPage->nCell++] = pCell;
   499    528       idx = pCell->h.iNext;
   500    529     }
................................................................................
   530    559     memset(pPage, 0, SQLITE_PAGE_SIZE);
   531    560     pHdr = &pPage->u.hdr;
   532    561     pHdr->firstCell = 0;
   533    562     pHdr->firstFree = sizeof(*pHdr);
   534    563     pFBlk = (FreeBlk*)&pHdr[1];
   535    564     pFBlk->iNext = 0;
   536    565     pFBlk->iSize = SQLITE_PAGE_SIZE - sizeof(*pHdr);
          566  +  pPage->nFree = pFBlk->iSize;
          567  +  pPage->nCell = 0;
          568  +  pPage->isOverfull = 0;
   537    569   }
   538    570   
   539    571   /*
   540    572   ** This routine is called when the reference count for a page
   541    573   ** reaches zero.  We need to unref the pParent pointer when that
   542    574   ** happens.
   543    575   */
................................................................................
   555    587   **
   556    588   ** Actually, this routine just sets up the internal data structures
   557    589   ** for accessing the database.  We do not open the database file 
   558    590   ** until the first page is loaded.
   559    591   */
   560    592   int sqliteBtreeOpen(const char *zFilename, int mode, Btree **ppBtree){
   561    593     Btree *pBt;
          594  +  int rc;
   562    595   
   563    596     pBt = sqliteMalloc( sizeof(*pBt) );
   564    597     if( pBt==0 ){
   565         -    **ppBtree = 0;
          598  +    *ppBtree = 0;
   566    599       return SQLITE_NOMEM;
   567    600     }
   568         -  rc = sqlitepager_open(&pBt->pPager, zFilename, 100, EXTRA_SPACE);
          601  +  rc = sqlitepager_open(&pBt->pPager, zFilename, 100, EXTRA_SIZE);
   569    602     if( rc!=SQLITE_OK ){
   570    603       if( pBt->pPager ) sqlitepager_close(pBt->pPager);
   571    604       sqliteFree(pBt);
   572    605       *ppBtree = 0;
   573    606       return rc;
   574    607     }
   575    608     sqlitepager_set_destructor(pBt->pPager, pageDestructor);
................................................................................
   600    633   ** SQLITE_BUSY is returned if the database is locked.  SQLITE_NOMEM
   601    634   ** is returned if we run out of memory.  SQLITE_PROTOCOL is returned
   602    635   ** if there is a locking protocol violation.
   603    636   */
   604    637   static int lockBtree(Btree *pBt){
   605    638     int rc;
   606    639     if( pBt->page1 ) return SQLITE_OK;
   607         -  rc = sqlitepager_get(pBt->pPager, 1, &pBt->page1);
          640  +  rc = sqlitepager_get(pBt->pPager, 1, (void**)&pBt->page1);
   608    641     if( rc!=SQLITE_OK ) return rc;
   609    642   
   610    643     /* Do some checking to help insure the file we opened really is
   611    644     ** a valid database file. 
   612    645     */
   613    646     if( sqlitepager_pagecount(pBt->pPager)>0 ){
   614    647       PageOne *pP1 = pBt->page1;
   615         -    if( strcmp(pP1->zMagic1,zMagicHeader)!=0 ){
          648  +    if( strcmp(pP1->zMagic,zMagicHeader)!=0 || pP1->iMagic!=MAGIC ){
   616    649         rc = SQLITE_CORRUPT;
   617    650         goto page1_init_failed;
   618    651       }
   619    652     }
   620    653     return rc;
   621    654   
   622    655   page1_init_failed:
   623    656     sqlitepager_unref(pBt->page1);
   624    657     pBt->page1 = 0;
   625    658     return rc;
   626    659   }
   627    660   
   628    661   /*
   629         -** Create a new database by initializing the first two pages.
          662  +** Create a new database by initializing the first two pages of the
          663  +** file.
   630    664   */
   631    665   static int newDatabase(Btree *pBt){
   632    666     MemPage *pRoot;
   633    667     PageOne *pP1;
          668  +  int rc;
   634    669     if( sqlitepager_pagecount(pBt->pPager)>0 ) return SQLITE_OK;
   635    670     pP1 = pBt->page1;
   636    671     rc = sqlitepager_write(pBt->page1);
   637    672     if( rc ) return rc;
   638         -  rc = sqlitepager_get(pBt->pPager, 2, &pRoot);
          673  +  rc = sqlitepager_get(pBt->pPager, 2, (void**)&pRoot);
   639    674     if( rc ) return rc;
   640    675     rc = sqlitepager_write(pRoot);
   641    676     if( rc ){
   642    677       sqlitepager_unref(pRoot);
   643    678       return rc;
   644    679     }
   645    680     strcpy(pP1->zMagic, zMagicHeader);
          681  +  pP1->iMagic = MAGIC;
   646    682     zeroPage(pRoot);
   647    683     sqlitepager_unref(pRoot);
   648    684     return SQLITE_OK;
   649    685   }
   650    686   
   651    687   /*
   652    688   ** Attempt to start a new transaction.
................................................................................
   660    696   **      sqliteBtreeDropTable()
   661    697   **      sqliteBtreeInsert()
   662    698   **      sqliteBtreeDelete()
   663    699   **      sqliteBtreeUpdateMeta()
   664    700   */
   665    701   int sqliteBtreeBeginTrans(Btree *pBt){
   666    702     int rc;
   667         -  PageOne *pP1;
   668    703     if( pBt->inTrans ) return SQLITE_ERROR;
   669    704     if( pBt->page1==0 ){
   670    705       rc = lockBtree(pBt);
   671         -    if( rc!=SQLITE_OK ) return rc;
          706  +    if( rc!=SQLITE_OK ){
          707  +      return rc;
          708  +    }
   672    709     }
   673    710     rc = sqlitepager_write(pBt->page1);
   674         -  if( rc==SQLITE_OK ){
   675         -    pBt->inTrans = 1;
          711  +  if( rc!=SQLITE_OK ){
          712  +    return rc;
   676    713     }
   677         -  return newDatabase(pBt);
          714  +  pBt->inTrans = 1;
          715  +  rc = newDatabase(pBt);
          716  +  return rc;
   678    717   }
   679    718   
   680    719   /*
   681    720   ** Remove the last reference to the database file.  This will
   682    721   ** remove the read lock.
   683    722   */
   684    723   static void unlockBtree(Btree *pBt){
................................................................................
   730    769     }
   731    770     pCur = sqliteMalloc( sizeof(*pCur) );
   732    771     if( pCur==0 ){
   733    772       rc = SQLITE_NOMEM;
   734    773       goto create_cursor_exception;
   735    774     }
   736    775     pCur->pgnoRoot = (Pgno)iTable;
   737         -  rc = sqlitepager_get(pBt->pPager, pCur->pgnoRoot, &pCur->pPage);
          776  +  rc = sqlitepager_get(pBt->pPager, pCur->pgnoRoot, (void**)&pCur->pPage);
   738    777     if( rc!=SQLITE_OK ){
   739    778       goto create_cursor_exception;
   740    779     }
   741    780     rc = initPage(pCur->pPage, pCur->pgnoRoot, 0);
   742    781     if( rc!=SQLITE_OK ){
   743    782       goto create_cursor_exception;
   744    783     }
................................................................................
   755    794   
   756    795   create_cursor_exception:
   757    796     *ppCur = 0;
   758    797     if( pCur ){
   759    798       if( pCur->pPage ) sqlitepager_unref(pCur->pPage);
   760    799       sqliteFree(pCur);
   761    800     }
   762         -  unlinkBtree(pBt);
          801  +  unlockBtree(pBt);
   763    802     return rc;
   764    803   }
   765    804   
   766    805   /*
   767    806   ** Close a cursor.  The lock on the database file is released
   768    807   ** when the last cursor is closed.
   769    808   */
   770    809   int sqliteBtreeCloseCursor(BtCursor *pCur){
   771    810     Btree *pBt = pCur->pBt;
   772         -  int i;
   773    811     if( pCur->pPrev ){
   774    812       pCur->pPrev->pNext = pCur->pNext;
   775    813     }else{
   776    814       pBt->pCursor = pCur->pNext;
   777    815     }
   778    816     if( pCur->pNext ){
   779    817       pCur->pNext->pPrev = pCur->pPrev;
   780    818     }
   781    819     sqlitepager_unref(pCur->pPage);
   782    820     unlockBtree(pBt);
   783    821     sqliteFree(pCur);
          822  +  return SQLITE_OK;
   784    823   }
   785    824   
   786    825   /*
   787    826   ** Make a temporary cursor by filling in the fields of pTempCur.
   788    827   ** The temporary cursor is not on the cursor list for the Btree.
   789    828   */
   790    829   static void getTempCursor(BtCursor *pCur, BtCursor *pTempCur){
................................................................................
   815    854   
   816    855     pPage = pCur->pPage;
   817    856     assert( pPage!=0 );
   818    857     if( pCur->idx >= pPage->nCell ){
   819    858       *pSize = 0;
   820    859     }else{
   821    860       pCell = pPage->apCell[pCur->idx];
   822         -    *psize = pCell->h.nKey;
          861  +    *pSize = pCell->h.nKey;
   823    862     }
   824    863     return SQLITE_OK;
   825    864   }
   826    865   
   827    866   /*
   828    867   ** Read payload information from the entry that the pCur cursor is
   829    868   ** pointing to.  Begin reading the payload at "offset" and read
................................................................................
   831    870   **
   832    871   ** This routine does not make a distinction between key and data.
   833    872   ** It just reads bytes from the payload area.
   834    873   */
   835    874   static int getPayload(BtCursor *pCur, int offset, int amt, char *zBuf){
   836    875     char *aPayload;
   837    876     Pgno nextPage;
          877  +  int rc;
   838    878     assert( pCur!=0 && pCur->pPage!=0 );
   839         -  assert( pCur->idx>=0 && pCur->idx<pCur->nCell );
   840         -  aPayload = pCur->pPage->apCell[pCur->idx].aPayload;
          879  +  assert( pCur->idx>=0 && pCur->idx<pCur->pPage->nCell );
          880  +  aPayload = pCur->pPage->apCell[pCur->idx]->aPayload;
   841    881     if( offset<MX_LOCAL_PAYLOAD ){
   842    882       int a = amt;
   843    883       if( a+offset>MX_LOCAL_PAYLOAD ){
   844    884         a = MX_LOCAL_PAYLOAD - offset;
   845    885       }
   846    886       memcpy(zBuf, &aPayload[offset], a);
   847    887       if( a==amt ){
................................................................................
   848    888         return SQLITE_OK;
   849    889       }
   850    890       offset += a;
   851    891       zBuf += a;
   852    892       amt -= a;
   853    893     }
   854    894     if( amt>0 ){
   855         -    nextPage = pCur->pPage->apCell[pCur->idx].ovfl;
          895  +    nextPage = pCur->pPage->apCell[pCur->idx]->ovfl;
   856    896     }
   857    897     while( amt>0 && nextPage ){
   858    898       OverflowPage *pOvfl;
   859         -    rc = sqlitepager_get(pCur->pBt->pPager, nextPage, &pOvfl);
          899  +    rc = sqlitepager_get(pCur->pBt->pPager, nextPage, (void**)&pOvfl);
   860    900       if( rc!=0 ){
   861    901         return rc;
   862    902       }
   863    903       nextPage = pOvfl->iNext;
   864    904       if( offset<OVERFLOW_SIZE ){
   865    905         int a = amt;
   866    906         if( a + offset > OVERFLOW_SIZE ){
................................................................................
   960   1000   ** is on overflow pages and we are unable to access those overflow
   961   1001   ** pages, then some other value might be returned to indicate the
   962   1002   ** reason for the error.
   963   1003   */
   964   1004   static int compareKey(BtCursor *pCur, char *pKey, int nKeyOrig, int *pResult){
   965   1005     Pgno nextPage;
   966   1006     int nKey = nKeyOrig;
   967         -  int n;
         1007  +  int n, c, rc;
   968   1008     Cell *pCell;
   969   1009   
   970   1010     assert( pCur->pPage );
   971   1011     assert( pCur->idx>=0 && pCur->idx<pCur->pPage->nCell );
   972   1012     pCell = pCur->pPage->apCell[pCur->idx];
   973   1013     if( nKey > pCell->h.nKey ){
   974   1014       nKey = pCell->h.nKey;
................................................................................
   986   1026     nKey -= n;
   987   1027     nextPage = pCell->ovfl;
   988   1028     while( nKey>0 ){
   989   1029       OverflowPage *pOvfl;
   990   1030       if( nextPage==0 ){
   991   1031         return SQLITE_CORRUPT;
   992   1032       }
   993         -    rc = sqlitepager_get(pCur->pBt->pPager, nextPage, &pOvfl);
         1033  +    rc = sqlitepager_get(pCur->pBt->pPager, nextPage, (void**)&pOvfl);
   994   1034       if( rc ){
   995   1035         return rc;
   996   1036       }
   997   1037       nextPage = pOvfl->iNext;
   998   1038       n = nKey;
   999   1039       if( n>OVERFLOW_SIZE ){
  1000   1040         n = OVERFLOW_SIZE;
................................................................................
  1016   1056   /*
  1017   1057   ** Move the cursor down to a new child page.
  1018   1058   */
  1019   1059   static int moveToChild(BtCursor *pCur, int newPgno){
  1020   1060     int rc;
  1021   1061     MemPage *pNewPage;
  1022   1062   
  1023         -  rc = sqlitepager_get(pCur->pBt->pPager, newPgno, &pNewPage);
         1063  +  rc = sqlitepager_get(pCur->pBt->pPager, newPgno, (void**)&pNewPage);
  1024   1064     if( rc ){
  1025   1065       return rc;
  1026   1066     }
  1027   1067     initPage(pNewPage, newPgno, pCur->pPage);
  1028   1068     sqlitepager_unref(pCur->pPage);
  1029   1069     pCur->pPage = pNewPage;
  1030   1070     pCur->idx = 0;
................................................................................
  1038   1078   ** to the page we are coming from.  If we are coming from the
  1039   1079   ** right-most child page then pCur->idx is set to one more than
  1040   1080   ** the largest cell index.
  1041   1081   */
  1042   1082   static int moveToParent(BtCursor *pCur){
  1043   1083     Pgno oldPgno;
  1044   1084     MemPage *pParent;
  1045         -
         1085  +  int i;
  1046   1086     pParent = pCur->pPage->pParent;
  1047   1087     if( pParent==0 ) return SQLITE_INTERNAL;
  1048   1088     oldPgno = sqlitepager_pagenumber(pCur->pPage);
  1049   1089     sqlitepager_ref(pParent);
  1050   1090     sqlitepager_unref(pCur->pPage);
  1051   1091     pCur->pPage = pParent;
  1052         -  pCur->idx = pPage->nCell;
  1053         -  for(i=0; i<pPage->nCell; i++){
  1054         -    if( pPage->apCell[i].h.leftChild==oldPgno ){
         1092  +  pCur->idx = pParent->nCell;
         1093  +  for(i=0; i<pParent->nCell; i++){
         1094  +    if( pParent->apCell[i]->h.leftChild==oldPgno ){
  1055   1095         pCur->idx = i;
  1056   1096         break;
  1057   1097       }
  1058   1098     }
  1059   1099     return SQLITE_OK;
  1060   1100   }
  1061   1101   
................................................................................
  1062   1102   /*
  1063   1103   ** Move the cursor to the root page
  1064   1104   */
  1065   1105   static int moveToRoot(BtCursor *pCur){
  1066   1106     MemPage *pNew;
  1067   1107     int rc;
  1068   1108   
  1069         -  rc = sqlitepager_get(pCur->pBt->pPager, pCur->pgnoRoot, &pNew);
         1109  +  rc = sqlitepager_get(pCur->pBt->pPager, pCur->pgnoRoot, (void**)&pNew);
  1070   1110     if( rc ) return rc;
  1071   1111     sqlitepager_unref(pCur->pPage);
  1072   1112     pCur->pPage = pNew;
  1073   1113     pCur->idx = 0;
  1074   1114     return SQLITE_OK;
  1075   1115   }
  1076   1116   
................................................................................
  1166   1206     if( pCur->bSkipNext ){
  1167   1207       pCur->bSkipNext = 0;
  1168   1208       if( pRes ) *pRes = 0;
  1169   1209       return SQLITE_OK;
  1170   1210     }
  1171   1211     pCur->idx++;
  1172   1212     if( pCur->idx>=pCur->pPage->nCell ){
  1173         -    if( pPage->u.hdr.rightChild ){
  1174         -      rc = moveToChild(pCur, pPage->u.hdr.rightChild);
         1213  +    if( pCur->pPage->u.hdr.rightChild ){
         1214  +      rc = moveToChild(pCur, pCur->pPage->u.hdr.rightChild);
  1175   1215         if( rc ) return rc;
  1176   1216         rc = moveToLeftmost(pCur);
  1177   1217         if( rc ) return rc;
  1178   1218         if( pRes ) *pRes = 0;
  1179   1219         return SQLITE_OK;
  1180   1220       }
  1181   1221       do{
  1182         -      if( pCur->pParent==0 ){
         1222  +      if( pCur->pPage->pParent==0 ){
  1183   1223           if( pRes ) *pRes = 1;
  1184   1224           return SQLITE_OK;
  1185   1225         }
  1186   1226         rc = moveToParent(pCur);
  1187   1227         if( rc ) return rc;
  1188   1228       }while( pCur->idx>=pCur->pPage->nCell );
  1189   1229       if( pRes ) *pRes = 0;
................................................................................
  1205   1245   **
  1206   1246   ** SQLITE_OK is returned on success.  Any other return value indicates
  1207   1247   ** an error.  *ppPage and *pPgno are undefined in the event of an error.
  1208   1248   ** Do not invoke sqlitepager_unref() on *ppPage if an error is returned.
  1209   1249   */
  1210   1250   static int allocatePage(Btree *pBt, MemPage **ppPage, Pgno *pPgno){
  1211   1251     PageOne *pPage1 = pBt->page1;
         1252  +  int rc;
  1212   1253     if( pPage1->freeList ){
  1213   1254       OverflowPage *pOvfl;
  1214   1255       rc = sqlitepager_write(pPage1);
  1215   1256       if( rc ) return rc;
  1216   1257       *pPgno = pPage1->freeList;
  1217         -    rc = sqlitepager_get(pBt->pPager, pPage1->freeList, &pOvfl);
         1258  +    rc = sqlitepager_get(pBt->pPager, pPage1->freeList, (void**)&pOvfl);
  1218   1259       if( rc ) return rc;
  1219   1260       rc = sqlitepager_write(pOvfl);
  1220   1261       if( rc ){
  1221   1262         sqlitepager_unref(pOvfl);
  1222   1263         return rc;
  1223   1264       }
  1224   1265       pPage1->freeList = pOvfl->iNext;
  1225   1266       *ppPage = (MemPage*)pOvfl;
  1226   1267     }else{
  1227   1268       *pPgno = sqlitepager_pagecount(pBt->pPager);
  1228         -    rc = sqlitepager_get(pBt->pPager, *pPgno, ppPage);
         1269  +    rc = sqlitepager_get(pBt->pPager, *pPgno, (void**)ppPage);
  1229   1270       if( rc ) return rc;
  1230   1271       rc = sqlitepager_write(*ppPage);
  1231   1272     }
  1232   1273     return rc;
  1233   1274   }
  1234   1275   
  1235   1276   /*
................................................................................
  1251   1292     }
  1252   1293     rc = sqlitepager_write(pPage1);
  1253   1294     if( rc ){
  1254   1295       return rc;
  1255   1296     }
  1256   1297     if( pOvfl==0 ){
  1257   1298       assert( pgno>0 );
  1258         -    rc = sqlitepager_get(pBt->pPager, pgno, &pOvfl);
         1299  +    rc = sqlitepager_get(pBt->pPager, pgno, (void**)&pOvfl);
  1259   1300       if( rc ) return rc;
  1260   1301       needOvflUnref = 1;
  1261   1302     }
  1262   1303     rc = sqlitepager_write(pOvfl);
  1263   1304     if( rc ){
  1264   1305       if( needOvflUnref ) sqlitepager_unref(pOvfl);
  1265   1306       return rc;
  1266   1307     }
  1267   1308     pOvfl->iNext = pPage1->freeList;
  1268   1309     pPage1->freeList = pgno;
  1269   1310     memset(pOvfl->aPayload, 0, OVERFLOW_SIZE);
  1270         -  pPage->isInit = 0;
  1271         -  assert( pPage->pParent==0 );
         1311  +  ((MemPage*)pPage)->isInit = 0;
         1312  +  assert( ((MemPage*)pPage)->pParent==0 );
  1272   1313     rc = sqlitepager_unref(pOvfl);
  1273   1314     return rc;
  1274   1315   }
  1275   1316   
  1276   1317   /*
  1277   1318   ** Erase all the data out of a cell.  This involves returning overflow
  1278   1319   ** pages back the freelist.
................................................................................
  1285   1326   
  1286   1327     if( pCell->h.nKey + pCell->h.nData <= MX_LOCAL_PAYLOAD ){
  1287   1328       return SQLITE_OK;
  1288   1329     }
  1289   1330     ovfl = pCell->ovfl;
  1290   1331     pCell->ovfl = 0;
  1291   1332     while( ovfl ){
  1292         -    rc = sqlitepager_get(pPager, ovfl, &pOvfl);
         1333  +    rc = sqlitepager_get(pPager, ovfl, (void**)&pOvfl);
  1293   1334       if( rc ) return rc;
  1294   1335       nextOvfl = pOvfl->iNext;
  1295   1336       rc = freePage(pBt, pOvfl, ovfl);
  1296   1337       if( rc ) return rc;
  1297   1338       ovfl = nextOvfl;
  1298   1339       sqlitepager_unref(pOvfl);
  1299   1340     }
................................................................................
  1306   1347   */
  1307   1348   static int fillInCell(
  1308   1349     Btree *pBt,              /* The whole Btree.  Needed to allocate pages */
  1309   1350     Cell *pCell,             /* Populate this Cell structure */
  1310   1351     void *pKey, int nKey,    /* The key */
  1311   1352     void *pData,int nData    /* The data */
  1312   1353   ){
  1313         -  int OverflowPage *pOvfl;
         1354  +  OverflowPage *pOvfl;
  1314   1355     Pgno *pNext;
  1315   1356     int spaceLeft;
  1316         -  int n;
         1357  +  int n, rc;
  1317   1358     int nPayload;
  1318   1359     char *pPayload;
  1319   1360     char *pSpace;
  1320   1361   
  1321   1362     pCell->h.leftChild = 0;
  1322   1363     pCell->h.nKey = nKey;
  1323   1364     pCell->h.nData = nData;
................................................................................
  1327   1368     pSpace = pCell->aPayload;
  1328   1369     spaceLeft = MX_LOCAL_PAYLOAD;
  1329   1370     pPayload = pKey;
  1330   1371     pKey = 0;
  1331   1372     nPayload = nKey;
  1332   1373     while( nPayload>0 ){
  1333   1374       if( spaceLeft==0 ){
  1334         -      rc = allocatePage(pBt, &pOvfl, pNext);
         1375  +      rc = allocatePage(pBt, (MemPage**)&pOvfl, pNext);
  1335   1376         if( rc ){
  1336   1377           *pNext = 0;
  1337   1378           clearCell(pBt, pCell);
  1338   1379           return rc;
  1339   1380         }
  1340   1381         spaceLeft = OVERFLOW_SIZE;
  1341   1382         pSpace = pOvfl->aPayload;
  1342         -      pNextPg = &pOvfl->iNext;
         1383  +      pNext = &pOvfl->iNext;
  1343   1384       }
  1344   1385       n = nPayload;
  1345   1386       if( n>spaceLeft ) n = spaceLeft;
  1346   1387       memcpy(pSpace, pPayload, n);
  1347   1388       nPayload -= n;
  1348   1389       if( nPayload==0 && pData ){
  1349   1390         pPayload = pData;
................................................................................
  1379   1420   ** Reparent all children of the given page to be the given page.
  1380   1421   ** In other words, for every child of pPage, invoke reparentPage()
  1381   1422   ** to make sure that child knows that pPage is its parent.
  1382   1423   **
  1383   1424   ** This routine gets called after you memcpy() one page into
  1384   1425   ** another.
  1385   1426   */
  1386         -static void reparentChildPages(Pager *pPager, Page *pPage){
         1427  +static void reparentChildPages(Pager *pPager, MemPage *pPage){
  1387   1428     int i;
  1388   1429     for(i=0; i<pPage->nCell; i++){
  1389         -    reparentPage(pPager, pPage->apCell[i]->leftChild, pPage);
         1430  +    reparentPage(pPager, pPage->apCell[i]->h.leftChild, pPage);
  1390   1431     }
  1391   1432     reparentPage(pPager, pPage->u.hdr.rightChild, pPage);
  1392   1433   }
  1393   1434   
  1394   1435   /*
  1395   1436   ** Remove the i-th cell from pPage.  This routine effects pPage only.
  1396   1437   ** The cell content is not freed or deallocated.  It is assumed that
  1397   1438   ** the cell content has been copied someplace else.  This routine just
  1398   1439   ** removes the reference to the cell from pPage.
  1399   1440   **
  1400   1441   ** "sz" must be the number of bytes in the cell.
  1401   1442   **
  1402   1443   ** Do not bother maintaining the integrity of the linked list of Cells.
  1403         -** Only pPage->apCell[] is important.  The relinkCellList() routine
  1404         -** will be called soon after this routine in order to rebuild the
  1405         -** linked list.
         1444  +** Only the pPage->apCell[] array is important.  The relinkCellList() 
         1445  +** routine will be called soon after this routine in order to rebuild 
         1446  +** the linked list.
  1406   1447   */
  1407         -static void dropCell(MemPage *pPage, int i, int sz){
         1448  +static void dropCell(MemPage *pPage, int idx, int sz){
  1408   1449     int j;
  1409         -  assert( i>=0 && i<pPage->nCell );
  1410         -  assert( sz==cellSize(pPage->apCell[i]);
         1450  +  assert( idx>=0 && idx<pPage->nCell );
         1451  +  assert( sz==cellSize(pPage->apCell[idx]) );
  1411   1452     freeSpace(pPage, idx, sz);
  1412         -  for(j=i, j<pPage->nCell-2; j++){
         1453  +  for(j=idx; j<pPage->nCell-2; j++){
  1413   1454       pPage->apCell[j] = pPage->apCell[j+1];
  1414   1455     }
  1415   1456     pPage->nCell--;
  1416   1457   }
  1417   1458   
  1418   1459   /*
  1419   1460   ** Insert a new cell on pPage at cell index "i".  pCell points to the
................................................................................
  1420   1461   ** content of the cell.
  1421   1462   **
  1422   1463   ** If the cell content will fit on the page, then put it there.  If it
  1423   1464   ** will not fit, then just make pPage->apCell[i] point to the content
  1424   1465   ** and set pPage->isOverfull.  
  1425   1466   **
  1426   1467   ** Do not bother maintaining the integrity of the linked list of Cells.
  1427         -** Only pPage->apCell[] is important.  The relinkCellList() routine
  1428         -** will be called soon after this routine in order to rebuild the
  1429         -** linked list.
         1468  +** Only the pPage->apCell[] array is important.  The relinkCellList() 
         1469  +** routine will be called soon after this routine in order to rebuild 
         1470  +** the linked list.
  1430   1471   */
  1431   1472   static void insertCell(MemPage *pPage, int i, Cell *pCell, int sz){
  1432   1473     int idx, j;
  1433   1474     assert( i>=0 && i<=pPage->nCell );
  1434   1475     assert( sz==cellSize(pCell) );
  1435   1476     for(j=pPage->nCell; j>i; j--){
  1436   1477       pPage->apCell[j] = pPage->apCell[j-1];
................................................................................
  1438   1479     pPage->nCell++;
  1439   1480     idx = allocateSpace(pPage, sz);
  1440   1481     if( idx<=0 ){
  1441   1482       pPage->isOverfull = 1;
  1442   1483       pPage->apCell[i] = pCell;
  1443   1484     }else{
  1444   1485       memcpy(&pPage->u.aDisk[idx], pCell, sz);
  1445         -    pPage->apCell[i] = (Cell*)&pPage->u.aDisk[idx]);
         1486  +    pPage->apCell[i] = (Cell*)&pPage->u.aDisk[idx];
  1446   1487     }
  1447   1488   }
  1448   1489   
  1449   1490   /*
  1450   1491   ** Rebuild the linked list of cells on a page so that the cells
  1451         -** occur in the order specified by pPage->apCell[].  Invoke this
  1452         -** routine once to repair damage after one or more invocations
  1453         -** of either insertCell() or dropCell().
         1492  +** occur in the order specified by the pPage->apCell[] array.  
         1493  +** Invoke this routine once to repair damage after one or more
         1494  +** invocations of either insertCell() or dropCell().
  1454   1495   */
  1455   1496   static void relinkCellList(MemPage *pPage){
  1456   1497     int i;
  1457   1498     u16 *pIdx;
  1458   1499     pIdx = &pPage->u.hdr.firstCell;
  1459   1500     for(i=0; i<pPage->nCell; i++){
  1460         -    int idx = ((uptr)pPage->apCell[i]) - (uptr)pPage;
         1501  +    int idx = addr(pPage->apCell[i]) - addr(pPage);
         1502  +    assert( idx>0 && idx<SQLITE_PAGE_SIZE );
  1461   1503       *pIdx = idx;
  1462   1504       pIdx = &pPage->apCell[i]->h.iNext;
  1463   1505     }
  1464   1506     *pIdx = 0;
  1465   1507   }
  1466   1508   
  1467   1509   /*
................................................................................
  1475   1517     int i;
  1476   1518     memcpy(pTo->u.aDisk, pFrom->u.aDisk, SQLITE_PAGE_SIZE);
  1477   1519     pTo->pParent = pFrom->pParent;
  1478   1520     pTo->isInit = 1;
  1479   1521     pTo->nCell = pFrom->nCell;
  1480   1522     pTo->nFree = pFrom->nFree;
  1481   1523     pTo->isOverfull = pFrom->isOverfull;
  1482         -  to = (unsigned int)pTo;
  1483         -  from = (unsigned int)pFrom;
         1524  +  to = addr(pTo);
         1525  +  from = addr(pFrom);
  1484   1526     for(i=0; i<pTo->nCell; i++){
  1485         -    uptr addr = (uptr)(pFrom->apCell[i]);
  1486         -    if( addr>from && addr<from+SQLITE_PAGE_SIZE ){
  1487         -      *((uptr*)&pTo->apCell[i]) = addr + to - from;
         1527  +    uptr x = addr(pFrom->apCell[i]);
         1528  +    if( x>from && x<from+SQLITE_PAGE_SIZE ){
         1529  +      *((uptr*)&pTo->apCell[i]) = x + to - from;
  1488   1530       }
  1489   1531     }
  1490   1532   }
  1491   1533   
  1492   1534   /*
  1493   1535   ** This routine redistributes Cells on pPage and up to two siblings
  1494   1536   ** of pPage so that all pages have about the same amount of free space.
................................................................................
  1495   1537   ** Usually one sibling on either side of pPage is used in the balancing,
  1496   1538   ** though both siblings might come from one side if pPage is the first
  1497   1539   ** or last child of its parent.  If pPage has fewer than two siblings
  1498   1540   ** (something which can only happen if pPage is the root page or a 
  1499   1541   ** child of root) then all available siblings participate in the balancing.
  1500   1542   **
  1501   1543   ** The number of siblings of pPage might be increased or decreased by
  1502         -** one in order to keep all pages between 2/3 and completely full.  If
  1503         -** pPage is the root page, then the depth of the tree might be increased
         1544  +** one in an effort to keep pages between 66% and 100% full. The root page
         1545  +** is special and is allowed to be less than 66% full. If pPage is 
         1546  +** the root page, then the depth of the tree might be increased
  1504   1547   ** or decreased by one, as necessary, to keep the root page from being
  1505   1548   ** overfull or empty.
  1506   1549   **
  1507   1550   ** This routine calls relinkCellList() on its input page regardless of
  1508   1551   ** whether or not it does any real balancing.  Client routines will typically
  1509   1552   ** invoke insertCell() or dropCell() before calling this routine, so we
  1510   1553   ** need to call relinkCellList() to clean up the mess that those other
  1511   1554   ** routines left behind.
  1512   1555   **
  1513   1556   ** pCur is left pointing to the same cell as when this routine was called
  1514         -** event if that cell gets moved to a different page.  pCur may be NULL.
         1557  +** even if that cell gets moved to a different page.  pCur may be NULL.
         1558  +** Set the pCur parameter to NULL if you do not care about keeping track
         1559  +** of a cell as that will save this routine the work of keeping track of it.
  1515   1560   **
  1516   1561   ** Note that when this routine is called, some of the Cells on pPage
  1517   1562   ** might not actually be stored in pPage->u.aDisk[].  This can happen
  1518   1563   ** if the page is overfull.  Part of the job of this routine is to
  1519   1564   ** make sure all Cells for pPage once again fit in pPage->u.aDisk[].
         1565  +**
         1566  +** In the course of balancing the siblings of pPage, the parent of pPage
         1567  +** might become overfull or underfull.  If that happens, then this routine
         1568  +** is called recursively on the parent.
  1520   1569   **
  1521   1570   ** If this routine fails for any reason, it means the database may have
  1522   1571   ** been left in a corrupted state and should be rolled back.
  1523   1572   */
  1524   1573   static int balance(Btree *pBt, MemPage *pPage, BtCursor *pCur){
  1525   1574     MemPage *pParent;            /* The parent of pPage */
  1526   1575     MemPage *apOld[3];           /* pPage and up to two siblings */
................................................................................
  1528   1577     MemPage *apNew[4];           /* pPage and up to 3 siblings after balancing */
  1529   1578     Pgno pgnoNew[4];             /* Page numbers for each page in apNew[] */
  1530   1579     int idxDiv[3];               /* Indices of divider cells in pParent */
  1531   1580     Cell *apDiv[3];              /* Divider cells in pParent */
  1532   1581     int nCell;                   /* Number of cells in apCell[] */
  1533   1582     int nOld;                    /* Number of pages in apOld[] */
  1534   1583     int nNew;                    /* Number of pages in apNew[] */
  1535         -  int perPage;                 /* Approximate number of bytes per page */
  1536   1584     int nDiv;                    /* Number of cells in apDiv[] */
  1537   1585     int i, j, k;                 /* Loop counters */
  1538   1586     int idx;                     /* Index of pPage in pParent->apCell[] */
  1539   1587     int nxDiv;                   /* Next divider slot in pParent->apCell[] */
  1540   1588     int rc;                      /* The return code */
  1541   1589     int iCur;                    /* apCell[iCur] is the cell of the cursor */
  1542   1590     int usedPerPage;             /* Memory needed for each page */
  1543   1591     int freePerPage;             /* Average free space per page */
         1592  +  int totalSize;               /* Total bytes for all cells */
         1593  +  Pgno pgno;                   /* Page number */
  1544   1594     Cell *apCell[MX_CELL*3+5];   /* All cells from pages being balanceed */
  1545   1595     int szCell[MX_CELL*3+5];     /* Local size of all cells */
  1546   1596     Cell aTemp[2];               /* Temporary holding area for apDiv[] */
  1547   1597     MemPage aOld[3];             /* Temporary copies of pPage and its siblings */
  1548   1598   
  1549   1599     /* 
  1550   1600     ** Return without doing any work if pPage is neither overfull nor
................................................................................
  1559   1609     ** Find the parent of the page to be balanceed.
  1560   1610     ** If there is no parent, it means this page is the root page and
  1561   1611     ** special rules apply.
  1562   1612     */
  1563   1613     pParent = pPage->pParent;
  1564   1614     if( pParent==0 ){
  1565   1615       Pgno pgnoChild;
  1566         -    Page *pChild;
         1616  +    MemPage *pChild;
  1567   1617       if( pPage->nCell==0 ){
  1568   1618         if( pPage->u.hdr.rightChild ){
  1569   1619           /*
  1570   1620           ** The root page is empty.  Copy the one child page
  1571   1621           ** into the root page and return.  This reduces the depth
  1572   1622           ** of the BTree by one.
  1573   1623           */
  1574   1624           rc = sqlitepager_write(pPage);
  1575   1625           if( rc ) return rc;
  1576   1626           pgnoChild = pPage->u.hdr.rightChild;
  1577         -        rc = sqlitepager_get(pBt, pgnoChild, &pChild);
         1627  +        rc = sqlitepager_get(pBt->pPager, pgnoChild, (void**)&pChild);
  1578   1628           if( rc ) return rc;
  1579   1629           memcpy(pPage, pChild, SQLITE_PAGE_SIZE);
  1580   1630           pPage->isInit = 0;
  1581   1631           initPage(pPage, sqlitepager_pagenumber(pPage), 0);
  1582   1632           reparentChildPages(pBt->pPager, pPage);
  1583   1633           freePage(pBt, pChild, pgnoChild);
  1584   1634           sqlitepager_unref(pChild);
................................................................................
  1664   1714     for(i=0, k=nxDiv; i<3; i++, k++){
  1665   1715       if( k<pParent->nCell ){
  1666   1716         idxDiv[i] = k;
  1667   1717         apDiv[i] = pParent->apCell[k];
  1668   1718         nDiv++;
  1669   1719         pgnoOld[i] = apDiv[i]->h.leftChild;
  1670   1720       }else if( k==pParent->nCell ){
  1671         -      pgnoOld[i] = pParent->rightChild;
         1721  +      pgnoOld[i] = pParent->u.hdr.rightChild;
  1672   1722       }else{
  1673   1723         break;
  1674   1724       }
  1675         -    rc = sqlitepager_get(pBt, pgnoOld[i], &apOld[i]);
         1725  +    rc = sqlitepager_get(pBt->pPager, pgnoOld[i], (void**)&apOld[i]);
  1676   1726       if( rc ) goto balance_cleanup;
  1677   1727       nOld++;
  1678   1728     }
  1679   1729   
  1680   1730     /*
  1681   1731     ** Set iCur to be the index in apCell[] of the cell that the cursor
  1682   1732     ** is pointing to.  We will need this later on in order to keep the
................................................................................
  1715   1765       for(j=0; j<pOld->nCell; j++){
  1716   1766         apCell[nCell] = pOld->apCell[j];
  1717   1767         szCell[nCell] = cellSize(apCell[nCell]);
  1718   1768         nCell++;
  1719   1769       }
  1720   1770       if( i<nOld-1 ){
  1721   1771         szCell[nCell] = cellSize(apDiv[i]);
  1722         -      memcpy(aTemp[i], apDiv[i], szCell[nCell]);
         1772  +      memcpy(&aTemp[i], apDiv[i], szCell[nCell]);
  1723   1773         apCell[nCell] = &aTemp[i];
  1724   1774         dropCell(pParent, nxDiv, szCell[nCell]);
  1725   1775         assert( apCell[nCell]->h.leftChild==pgnoOld[i] );
  1726   1776         apCell[nCell]->h.leftChild = pOld->u.hdr.rightChild;
  1727   1777         nCell++;
  1728   1778       }
  1729   1779     }
................................................................................
  1874   1924   ** sqliteBtreeNext() after a delete and the cursor will be left
  1875   1925   ** pointing to the first entry after the deleted entry.
  1876   1926   */
  1877   1927   int sqliteBtreeDelete(BtCursor *pCur){
  1878   1928     MemPage *pPage = pCur->pPage;
  1879   1929     Cell *pCell;
  1880   1930     int rc;
         1931  +  Pgno pgnoChild;
  1881   1932   
  1882   1933     if( !pCur->pBt->inTrans ){
  1883   1934       return SQLITE_ERROR;  /* Must start a transaction first */
  1884   1935     }
  1885   1936     if( pCur->idx >= pPage->nCell ){
  1886   1937       return SQLITE_ERROR;  /* The cursor is not pointing to anything */
  1887   1938     }
  1888   1939     rc = sqlitepager_write(pPage);
  1889   1940     if( rc ) return rc;
  1890   1941     pCell = pPage->apCell[pCur->idx];
  1891   1942     pgnoChild = pCell->h.leftChild;
  1892         -  clearCell(pCell);
         1943  +  clearCell(pCur->pBt, pCell);
  1893   1944     dropCell(pPage, pCur->idx, cellSize(pCell));
  1894   1945     if( pgnoChild ){
  1895   1946       /*
  1896   1947       ** If the entry we just deleted is not a leaf, then we've left a
  1897         -    ** whole in an internal page.  We have to fill the whole by moving
  1898         -    ** in a page from a leaf.  The next Cell after the one just deleted
         1948  +    ** hole in an internal page.  We have to fill the hole by moving
         1949  +    ** in a cell from a leaf.  The next Cell after the one just deleted
  1899   1950       ** is guaranteed to exist and to be a leaf so we can use it.
  1900   1951       */
  1901   1952       BtCursor leafCur;
  1902   1953       Cell *pNext;
  1903   1954       int szNext;
  1904   1955       getTempCursor(pCur, &leafCur);
  1905   1956       rc = sqliteBtreeNext(&leafCur, 0);
  1906   1957       if( rc!=SQLITE_OK ){
  1907   1958         return SQLITE_CORRUPT;
  1908   1959       }
  1909         -    pNext = leafCur.pPage->apCell[leafCur.idx]
         1960  +    pNext = leafCur.pPage->apCell[leafCur.idx];
  1910   1961       szNext = cellSize(pNext);
         1962  +    pNext->h.leftChild = pgnoChild;
  1911   1963       insertCell(pPage, pCur->idx, pNext, szNext);
  1912   1964       rc = balance(pCur->pBt, pPage, pCur);
  1913   1965       if( rc ) return rc;
  1914   1966       pCur->bSkipNext = 1;
  1915   1967       dropCell(leafCur.pPage, leafCur.idx, szNext);
  1916   1968       rc = balance(pCur->pBt, leafCur.pPage, 0);
  1917         -    releaseTempCur(&leafCur);
         1969  +    releaseTempCursor(&leafCur);
  1918   1970     }else{
  1919   1971       rc = balance(pCur->pBt, pPage, pCur);
  1920   1972       pCur->bSkipNext = 1;
  1921   1973     }
  1922   1974     return rc;
  1923   1975   }
  1924   1976   
................................................................................
  1945   1997   /*
  1946   1998   ** Erase the given database page and all its children.  Return
  1947   1999   ** the page to the freelist.
  1948   2000   */
  1949   2001   static int clearDatabasePage(Btree *pBt, Pgno pgno){
  1950   2002     MemPage *pPage;
  1951   2003     int rc;
  1952         -  int i;
  1953   2004     Cell *pCell;
  1954   2005     int idx;
  1955   2006   
  1956         -  rc = sqlitepager_get(pBt->pPager, pgno, &pPage);
         2007  +  rc = sqlitepager_get(pBt->pPager, pgno, (void**)&pPage);
  1957   2008     if( rc ) return rc;
  1958   2009     idx = pPage->u.hdr.firstCell;
  1959   2010     while( idx>0 ){
  1960   2011       pCell = (Cell*)&pPage->u.aDisk[idx];
  1961   2012       idx = pCell->h.iNext;
  1962   2013       if( pCell->h.leftChild ){
  1963   2014         rc = clearDatabasePage(pBt, pCell->h.leftChild);
  1964   2015         if( rc ) return rc;
  1965   2016       }
  1966         -    rc = clearCell(pCell);
         2017  +    rc = clearCell(pBt, pCell);
  1967   2018       if( rc ) return rc;
  1968   2019     }
         2020  +  rc = clearDatabasePage(pBt, pPage->u.hdr.rightChild);
         2021  +  if( rc ) return rc;
  1969   2022     return freePage(pBt, pPage, pgno);
  1970   2023   }
  1971   2024   
  1972   2025   /*
  1973   2026   ** Delete all information from a single table in the database.
  1974   2027   */
  1975   2028   int sqliteBtreeClearTable(Btree *pBt, int iTable){
................................................................................
  1976   2029     int rc;
  1977   2030     if( !pBt->inTrans ){
  1978   2031       return SQLITE_ERROR;  /* Must start a transaction first */
  1979   2032     }
  1980   2033     rc = clearDatabasePage(pBt, (Pgno)iTable);
  1981   2034     if( rc ){
  1982   2035       sqliteBtreeRollback(pBt);
  1983         -    return rc;
  1984   2036     }
         2037  +  return rc;
  1985   2038   }
  1986   2039   
  1987   2040   /*
  1988   2041   ** Erase all information in a table and add the root of the table to
  1989   2042   ** the freelist.  Except, the root of the principle table (the one on
  1990   2043   ** page 2) is never added to the freelist.
  1991   2044   */
  1992   2045   int sqliteBtreeDropTable(Btree *pBt, int iTable){
  1993   2046     int rc;
  1994   2047     MemPage *pPage;
  1995   2048     if( !pBt->inTrans ){
  1996   2049       return SQLITE_ERROR;  /* Must start a transaction first */
  1997   2050     }
  1998         -  rc = sqlitepager_get(pBt->pPager, (Pgno)iTable, &pPage);
         2051  +  rc = sqlitepager_get(pBt->pPager, (Pgno)iTable, (void**)&pPage);
  1999   2052     if( rc==SQLITE_OK ){
  2000   2053       rc = sqliteBtreeClearTable(pBt, iTable);
  2001   2054     }
  2002   2055     if( rc==SQLITE_OK && iTable!=2 ){
  2003   2056       rc = freePage(pBt, pPage, (Pgno)iTable);
  2004   2057     }
  2005   2058     sqlitepager_unref(pPage);
................................................................................
  2009   2062   /*
  2010   2063   ** Read the meta-information out of a database file.
  2011   2064   */
  2012   2065   int sqliteBtreeGetMeta(Btree *pBt, int *aMeta){
  2013   2066     PageOne *pP1;
  2014   2067     int rc;
  2015   2068   
  2016         -  rc = sqlitepager_get(pBt->pPager, 1, &pP1);
         2069  +  rc = sqlitepager_get(pBt->pPager, 1, (void**)&pP1);
  2017   2070     if( rc ) return rc;
  2018   2071     memcpy(aMeta, pP1->aMeta, sizeof(pP1->aMeta));
  2019   2072     sqlitepager_unref(pP1);
  2020   2073     return SQLITE_OK;
  2021   2074   }
  2022   2075   
  2023   2076   /*
................................................................................
  2031   2084     }
  2032   2085     pP1 = pBt->page1;
  2033   2086     rc = sqlitepager_write(pP1);
  2034   2087     if( rc ) return rc;
  2035   2088     memcpy(pP1->aMeta, aMeta, sizeof(pP1->aMeta));
  2036   2089     return SQLITE_OK;
  2037   2090   }
         2091  +
         2092  +#ifdef SQLITE_TEST
         2093  +/*
         2094  +** Print a disassembly of the given page on standard output.  This routine
         2095  +** is used for debugging and testing only.
         2096  +*/
         2097  +int sqliteBtreePageDump(Btree *pBt, int pgno){
         2098  +  int rc;
         2099  +  MemPage *pPage;
         2100  +  int i, j;
         2101  +  int nFree;
         2102  +  u16 idx;
         2103  +  char range[20];
         2104  +  unsigned char payload[20];
         2105  +  rc = sqlitepager_get(pBt->pPager, (Pgno)pgno, (void**)&pPage);
         2106  +  if( rc ){
         2107  +    return rc;
         2108  +  }
         2109  +  i = 0;
         2110  +  idx = pPage->u.hdr.firstCell;
         2111  +  while( idx>0 && idx<=SQLITE_PAGE_SIZE-MIN_CELL_SIZE ){
         2112  +    Cell *pCell = (Cell*)&pPage->u.aDisk[idx];
         2113  +    int sz = cellSize(pCell);
         2114  +    sprintf(range,"%d..%d", idx, idx+sz-1);
         2115  +    if( sz>sizeof(payload)-1 ) sz = sizeof(payload)-1;
         2116  +    memcpy(payload, pCell->aPayload, sz);
         2117  +    for(j=0; j<sz; j++){
         2118  +      if( payload[j]<0x20 || payload[j]>0x7f ) payload[j] = '.';
         2119  +    }
         2120  +    payload[sz] = 0;
         2121  +    printf(
         2122  +      "cell %2d: i=%-10s chld=%-4d nk=%-3d nd=%-3d payload=%s\n",
         2123  +      i, range, (int)pCell->h.leftChild, pCell->h.nKey, pCell->h.nData,
         2124  +      pCell->aPayload
         2125  +    );
         2126  +    idx = pCell->h.iNext;
         2127  +  }
         2128  +  if( idx!=0 ){
         2129  +    printf("ERROR: next cell index out of range: %d\n", idx);
         2130  +  }
         2131  +  printf("right_child: %d\n", pPage->u.hdr.rightChild);
         2132  +  nFree = 0;
         2133  +  i = 0;
         2134  +  idx = pPage->u.hdr.firstFree;
         2135  +  while( idx>0 && idx<SQLITE_PAGE_SIZE ){
         2136  +    FreeBlk *p = (FreeBlk*)&pPage->u.aDisk[idx];
         2137  +    sprintf(range,"%d..%d", idx, idx+p->iSize-1);
         2138  +    nFree += p->iSize;
         2139  +    printf("freeblock %2d: i=%-10s size=%-4d total=%d\n",
         2140  +       i, range, p->iSize, nFree);
         2141  +    idx = p->iNext;
         2142  +  }
         2143  +  if( idx!=0 ){
         2144  +    printf("ERROR: next freeblock index out of range: %d\n", idx);
         2145  +  }
         2146  +  sqlitepager_unref(pPage);
         2147  +  return SQLITE_OK;
         2148  +}
         2149  +#endif
         2150  +
         2151  +#ifdef SQLITE_TEST
         2152  +/*
         2153  +** Put the page number and index of a cursor into aResult[0] and aResult[1]
         2154  +** This routine is used for debugging and testing only.
         2155  +*/
         2156  +int sqliteBtreeCursorDump(BtCursor *pCur, int *aResult){
         2157  +  aResult[0] = sqlitepager_pagenumber(pCur->pPage);
         2158  +  aResult[1] = pCur->idx;
         2159  +  return SQLITE_OK;
         2160  +}
         2161  +#endif

Changes to src/btree.h.

    20     20   **   drh@hwaci.com
    21     21   **   http://www.hwaci.com/drh/
    22     22   **
    23     23   *************************************************************************
    24     24   ** This header file defines the interface that the sqlite B-Tree file
    25     25   ** subsystem.
    26     26   **
    27         -** @(#) $Id: btree.h,v 1.4 2001/06/08 00:21:53 drh Exp $
           27  +** @(#) $Id: btree.h,v 1.5 2001/06/22 19:15:00 drh Exp $
    28     28   */
    29     29   
    30     30   typedef struct Btree Btree;
    31     31   typedef struct BtCursor BtCursor;
    32     32   
    33     33   int sqliteBtreeOpen(const char *zFilename, int mode, Btree **ppBtree);
    34     34   int sqliteBtreeClose(Btree*);
................................................................................
    38     38   int sqliteBtreeRollback(Btree*);
    39     39   
    40     40   int sqliteBtreeCreateTable(Btree*, int*);
    41     41   int sqliteBtreeDropTable(Btree*, int);
    42     42   int sqliteBtreeClearTable(Btree*, int);
    43     43   
    44     44   int sqliteBtreeCursor(Btree*, int iTable, BtCursor **ppCur);
    45         -int sqliteBtreeMoveto(BtCursor*, void *pKey, int nKey, *pRes);
           45  +int sqliteBtreeMoveto(BtCursor*, void *pKey, int nKey, int *pRes);
    46     46   int sqliteBtreeDelete(BtCursor*);
    47     47   int sqliteBtreeInsert(BtCursor*, void *pKey, int nKey, void *pData, int nData);
    48     48   int sqliteBtreeNext(BtCursor*, int *pRes);
    49     49   int sqliteBtreeKeySize(BtCursor*, int *pSize);
    50     50   int sqliteBtreeKey(BtCursor*, int offset, int amt, char *zBuf);
    51     51   int sqliteBtreeDataSize(BtCursor*, int *pSize);
    52     52   int sqliteBtreeData(BtCursor*, int offset, int amt, char *zBuf);
    53     53   int sqliteBtreeCloseCursor(BtCursor*);
    54     54   
    55     55   #define SQLITE_N_BTREE_META 3
    56     56   int sqliteBtreeGetMeta(Btree*, int*);
    57     57   int sqliteBtreeUpdateMeta(Btree*, int*);
           58  +
           59  +
           60  +#ifdef SQLITE_TEST
           61  +int sqliteBtreePageDump(Btree*, int);
           62  +int sqliteBtreeCursorDump(BtCursor*, int*);
           63  +#endif

Changes to src/pager.c.

    23     23   *************************************************************************
    24     24   ** This is the implementation of the page cache subsystem.
    25     25   ** 
    26     26   ** The page cache is used to access a database file.  The pager journals
    27     27   ** all writes in order to support rollback.  Locking is used to limit
    28     28   ** access to one or more reader or one writer.
    29     29   **
    30         -** @(#) $Id: pager.c,v 1.8 2001/06/02 02:40:57 drh Exp $
           30  +** @(#) $Id: pager.c,v 1.9 2001/06/22 19:15:00 drh Exp $
    31     31   */
    32     32   #include "sqliteInt.h"
    33     33   #include "pager.h"
    34     34   #include <fcntl.h>
    35     35   #include <sys/stat.h>
    36     36   #include <unistd.h>
    37     37   #include <assert.h>
................................................................................
   558    558   }
   559    559   
   560    560   /*
   561    561   ** Increment the reference count for a page.  If the page is
   562    562   ** currently on the freelist (the reference count is zero) then
   563    563   ** remove it from the freelist.
   564    564   */
   565         -static void sqlitepager_ref(PgHdr *pPg){
          565  +int sqlitepager_ref(void *pData){
          566  +  PgHdr *pPg = DATA_TO_PGHDR(pData);
   566    567     if( pPg->nRef==0 ){
   567    568       /* The page is currently on the freelist.  Remove it. */
   568    569       if( pPg->pPrevFree ){
   569    570         pPg->pPrevFree->pNextFree = pPg->pNextFree;
   570    571       }else{
   571    572         pPg->pPager->pFirst = pPg->pNextFree;
   572    573       }
................................................................................
   574    575         pPg->pNextFree->pPrevFree = pPg->pPrevFree;
   575    576       }else{
   576    577         pPg->pPager->pLast = pPg->pPrevFree;
   577    578       }
   578    579       pPg->pPager->nRef++;
   579    580     }
   580    581     pPg->nRef++;
          582  +  return SQLITE_OK;
   581    583   }
   582    584   
   583    585   /*
   584    586   ** Acquire a page.
   585    587   **
   586    588   ** A read lock is obtained for the first page acquired.  The lock
   587    589   ** is dropped when the last page is released.  

Changes to src/pager.h.

    21     21   **   http://www.hwaci.com/drh/
    22     22   **
    23     23   *************************************************************************
    24     24   ** This header file defines the interface that the sqlite page cache
    25     25   ** subsystem.  The page cache subsystem reads and writes a file a page
    26     26   ** at a time and provides a journal for rollback.
    27     27   **
    28         -** @(#) $Id: pager.h,v 1.4 2001/05/24 21:06:36 drh Exp $
           28  +** @(#) $Id: pager.h,v 1.5 2001/06/22 19:15:01 drh Exp $
    29     29   */
    30     30   
    31     31   /*
    32     32   ** The size of one page
    33     33   */
    34     34   #define SQLITE_PAGE_SIZE 1024
    35     35   
................................................................................
    41     41   
    42     42   /*
    43     43   ** Each open file is managed by a separate instance of the "Pager" structure.
    44     44   */
    45     45   typedef struct Pager Pager;
    46     46   
    47     47   int sqlitepager_open(Pager **ppPager,const char *zFilename,int nPage,int nEx);
    48         -void sqiltepager_set_destructor(Pager*, void(*)(void*));
           48  +void sqlitepager_set_destructor(Pager*, void(*)(void*));
    49     49   int sqlitepager_close(Pager *pPager);
    50     50   int sqlitepager_get(Pager *pPager, Pgno pgno, void **ppPage);
    51     51   void *sqlitepager_lookup(Pager *pPager, Pgno pgno);
           52  +int sqlitepager_ref(void*);
    52     53   int sqlitepager_unref(void*);
    53     54   Pgno sqlitepager_pagenumber(void*);
    54     55   int sqlitepager_write(void*);
    55     56   int sqlitepager_pagecount(Pager*);
    56     57   int sqlitepager_commit(Pager*);
    57     58   int sqlitepager_rollback(Pager*);
    58     59   int *sqlitepager_stats(Pager*);

Changes to src/tclsqlite.c.

    19     19   ** Author contact information:
    20     20   **   drh@hwaci.com
    21     21   **   http://www.hwaci.com/drh/
    22     22   **
    23     23   *************************************************************************
    24     24   ** A TCL Interface to SQLite
    25     25   **
    26         -** $Id: tclsqlite.c,v 1.18 2001/04/15 00:37:09 drh Exp $
           26  +** $Id: tclsqlite.c,v 1.19 2001/06/22 19:15:01 drh Exp $
    27     27   */
    28     28   #ifndef NO_TCL     /* Omit this whole file if TCL is unavailable */
    29     29   
    30     30   #include "sqlite.h"
    31     31   #include "tcl.h"
    32     32   #include <stdlib.h>
    33     33   #include <string.h>
................................................................................
   507    507     Tcl_FindExecutable(argv[0]);
   508    508     interp = Tcl_CreateInterp();
   509    509     Sqlite_Init(interp);
   510    510   #ifdef SQLITE_TEST
   511    511     {
   512    512       extern int Sqlitetest1_Init(Tcl_Interp*);
   513    513       extern int Sqlitetest2_Init(Tcl_Interp*);
          514  +    extern int Sqlitetest3_Init(Tcl_Interp*);
   514    515       Sqlitetest1_Init(interp);
   515    516       Sqlitetest2_Init(interp);
          517  +    Sqlitetest3_Init(interp);
   516    518     }
   517    519   #endif
   518    520     if( argc>=2 ){
   519    521       int i;
   520    522       Tcl_SetVar(interp,"argv0",argv[1],TCL_GLOBAL_ONLY);
   521    523       Tcl_SetVar(interp,"argv", "", TCL_GLOBAL_ONLY);
   522    524       for(i=2; i<argc; i++){

Changes to src/test3.c.

    21     21   **   http://www.hwaci.com/drh/
    22     22   **
    23     23   *************************************************************************
    24     24   ** Code for testing the btree.c module in SQLite.  This code
    25     25   ** is not included in the SQLite library.  It is used for automated
    26     26   ** testing of the SQLite library.
    27     27   **
    28         -** $Id: test3.c,v 1.1 2001/06/02 02:40:57 drh Exp $
           28  +** $Id: test3.c,v 1.2 2001/06/22 19:15:01 drh Exp $
    29     29   */
    30     30   #include "sqliteInt.h"
    31     31   #include "pager.h"
    32     32   #include "btree.h"
    33     33   #include "tcl.h"
    34     34   #include <stdlib.h>
    35     35   #include <string.h>
................................................................................
    67     67   */
    68     68   static int btree_open(
    69     69     void *NotUsed,
    70     70     Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
    71     71     int argc,              /* Number of arguments */
    72     72     char **argv            /* Text of each argument */
    73     73   ){
    74         -  BTree *pBt;
    75         -  int nPage;
           74  +  Btree *pBt;
    76     75     int rc;
    77     76     char zBuf[100];
    78     77     if( argc!=2 ){
    79     78       Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
    80     79          " FILENAME\"", 0);
    81     80       return TCL_ERROR;
    82     81     }
................................................................................
   151    150   */
   152    151   static int btree_rollback(
   153    152     void *NotUsed,
   154    153     Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
   155    154     int argc,              /* Number of arguments */
   156    155     char **argv            /* Text of each argument */
   157    156   ){
   158         -  Btree *pBt
          157  +  Btree *pBt;
   159    158     int rc;
   160    159     if( argc!=2 ){
   161    160       Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
   162    161          " ID\"", 0);
   163    162       return TCL_ERROR;
   164    163     }
   165    164     if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR;
................................................................................
   235    234   */
   236    235   static int btree_drop_table(
   237    236     void *NotUsed,
   238    237     Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
   239    238     int argc,              /* Number of arguments */
   240    239     char **argv            /* Text of each argument */
   241    240   ){
   242         -  Pager *pPager;
          241  +  Btree *pBt;
          242  +  int iTable;
          243  +  int rc;
          244  +  if( argc!=3 ){
          245  +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
          246  +       " ID TABLENUM\"", 0);
          247  +    return TCL_ERROR;
          248  +  }
          249  +  if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR;
          250  +  if( Tcl_GetInt(interp, argv[2], &iTable) ) return TCL_ERROR;
          251  +  rc = sqliteBtreeDropTable(pBt, iTable);
          252  +  if( rc!=SQLITE_OK ){
          253  +    Tcl_AppendResult(interp, errorName(rc), 0);
          254  +    return TCL_ERROR;
          255  +  }
          256  +  return TCL_OK;
          257  +}
          258  +
          259  +/*
          260  +** Usage:   btree_get_meta ID
          261  +**
          262  +** Return meta data
          263  +*/
          264  +static int btree_get_meta(
          265  +  void *NotUsed,
          266  +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
          267  +  int argc,              /* Number of arguments */
          268  +  char **argv            /* Text of each argument */
          269  +){
          270  +  Btree *pBt;
          271  +  int rc;
          272  +  int i;
          273  +  int aMeta[SQLITE_N_BTREE_META];
          274  +  if( argc!=2 ){
          275  +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
          276  +       " ID\"", 0);
          277  +    return TCL_ERROR;
          278  +  }
          279  +  if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR;
          280  +  rc = sqliteBtreeGetMeta(pBt, aMeta);
          281  +  if( rc!=SQLITE_OK ){
          282  +    Tcl_AppendResult(interp, errorName(rc), 0);
          283  +    return TCL_ERROR;
          284  +  }
          285  +  for(i=0; i<SQLITE_N_BTREE_META; i++){
          286  +    char zBuf[30];
          287  +    sprintf(zBuf,"%d",aMeta[i]);
          288  +    Tcl_AppendElement(interp, zBuf);
          289  +  }
          290  +  return TCL_OK;
          291  +}
          292  +
          293  +/*
          294  +** Usage:   btree_update_meta ID METADATA...
          295  +**
          296  +** Return meta data
          297  +*/
          298  +static int btree_update_meta(
          299  +  void *NotUsed,
          300  +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
          301  +  int argc,              /* Number of arguments */
          302  +  char **argv            /* Text of each argument */
          303  +){
          304  +  Btree *pBt;
          305  +  int rc;
          306  +  int i;
          307  +  int aMeta[SQLITE_N_BTREE_META];
          308  +
          309  +  if( argc!=2+SQLITE_N_BTREE_META ){
          310  +    char zBuf[30];
          311  +    sprintf(zBuf,"%d",SQLITE_N_BTREE_META);
          312  +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
          313  +       " ID METADATA...\" (METADATA is ", zBuf, " integers)", 0);
          314  +    return TCL_ERROR;
          315  +  }
          316  +  if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR;
          317  +  for(i=0; i<SQLITE_N_BTREE_META; i++){
          318  +    if( Tcl_GetInt(interp, argv[i+2], &aMeta[i]) ) return TCL_ERROR;
          319  +  }
          320  +  rc = sqliteBtreeUpdateMeta(pBt, aMeta);
          321  +  if( rc!=SQLITE_OK ){
          322  +    Tcl_AppendResult(interp, errorName(rc), 0);
          323  +    return TCL_ERROR;
          324  +  }
          325  +  return TCL_OK;
          326  +}
          327  +
          328  +/*
          329  +** Usage:   btree_page_dump ID PAGENUM
          330  +**
          331  +** Print a disassembly of a page on standard output
          332  +*/
          333  +static int btree_page_dump(
          334  +  void *NotUsed,
          335  +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
          336  +  int argc,              /* Number of arguments */
          337  +  char **argv            /* Text of each argument */
          338  +){
          339  +  Btree *pBt;
          340  +  int iPage;
          341  +  int rc;
          342  +
          343  +  if( argc!=3 ){
          344  +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
          345  +       " ID\"", 0);
          346  +    return TCL_ERROR;
          347  +  }
          348  +  if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR;
          349  +  if( Tcl_GetInt(interp, argv[2], &iPage) ) return TCL_ERROR;
          350  +  rc = sqliteBtreePageDump(pBt, iPage);
          351  +  if( rc!=SQLITE_OK ){
          352  +    Tcl_AppendResult(interp, errorName(rc), 0);
          353  +    return TCL_ERROR;
          354  +  }
          355  +  return TCL_OK;
          356  +}
          357  +
          358  +/*
          359  +** Usage:   btree_cursor ID TABLENUM
          360  +**
          361  +** Create a new cursor.  Return the ID for the cursor.
          362  +*/
          363  +static int btree_cursor(
          364  +  void *NotUsed,
          365  +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
          366  +  int argc,              /* Number of arguments */
          367  +  char **argv            /* Text of each argument */
          368  +){
          369  +  Btree *pBt;
   243    370     int iTable;
   244         -  char zBuf[100];
          371  +  BtCursor *pCur;
          372  +  int rc;
          373  +  char zBuf[30];
          374  +
   245    375     if( argc!=3 ){
   246    376       Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
   247    377          " ID TABLENUM\"", 0);
   248    378       return TCL_ERROR;
   249    379     }
   250    380     if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR;
   251         -  if( Tcl_GetInt(interp, argv[2], &iTable ) return TCL_ERROR;
   252         -  rc = sqliteBtreeDropTable(pBt, iTable);
   253         -  if( rc!=SQLITE_OK ){
          381  +  if( Tcl_GetInt(interp, argv[2], &iTable) ) return TCL_ERROR;
          382  +  rc = sqliteBtreeCursor(pBt, iTable, &pCur);
          383  +  if( rc ){
          384  +    Tcl_AppendResult(interp, errorName(rc), 0);
          385  +    return TCL_ERROR;
          386  +  }
          387  +  sprintf(zBuf,"0x%x", (int)pCur);
          388  +  Tcl_AppendResult(interp, zBuf, 0);
          389  +  return SQLITE_OK;
          390  +}
          391  +
          392  +/*
          393  +** Usage:   btree_close_cursor ID
          394  +**
          395  +** Close a cursor opened using btree_cursor.
          396  +*/
          397  +static int btree_close_cursor(
          398  +  void *NotUsed,
          399  +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
          400  +  int argc,              /* Number of arguments */
          401  +  char **argv            /* Text of each argument */
          402  +){
          403  +  BtCursor *pCur;
          404  +  int rc;
          405  +
          406  +  if( argc!=2 ){
          407  +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
          408  +       " ID\"", 0);
          409  +    return TCL_ERROR;
          410  +  }
          411  +  if( Tcl_GetInt(interp, argv[1], (int*)&pCur) ) return TCL_ERROR;
          412  +  rc = sqliteBtreeCloseCursor(pCur);
          413  +  if( rc ){
          414  +    Tcl_AppendResult(interp, errorName(rc), 0);
          415  +    return TCL_ERROR;
          416  +  }
          417  +  return SQLITE_OK;
          418  +}
          419  +
          420  +/*
          421  +** Usage:   btree_move_to ID KEY
          422  +**
          423  +** Move the cursor to the entry with the given key.
          424  +*/
          425  +static int btree_move_to(
          426  +  void *NotUsed,
          427  +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
          428  +  int argc,              /* Number of arguments */
          429  +  char **argv            /* Text of each argument */
          430  +){
          431  +  BtCursor *pCur;
          432  +  int rc;
          433  +  int res;
          434  +  char zBuf[20];
          435  +
          436  +  if( argc!=3 ){
          437  +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
          438  +       " ID KEY\"", 0);
          439  +    return TCL_ERROR;
          440  +  }
          441  +  if( Tcl_GetInt(interp, argv[1], (int*)&pCur) ) return TCL_ERROR;
          442  +  rc = sqliteBtreeMoveto(pCur, argv[2], strlen(argv[2]), &res);  
          443  +  if( rc ){
          444  +    Tcl_AppendResult(interp, errorName(rc), 0);
          445  +    return TCL_ERROR;
          446  +  }
          447  +  sprintf(zBuf,"%d",res);
          448  +  Tcl_AppendResult(interp, zBuf, 0);
          449  +  return SQLITE_OK;
          450  +}
          451  +
          452  +/*
          453  +** Usage:   btree_delete ID
          454  +**
          455  +** Delete the entry that the cursor is pointing to
          456  +*/
          457  +static int btree_delete(
          458  +  void *NotUsed,
          459  +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
          460  +  int argc,              /* Number of arguments */
          461  +  char **argv            /* Text of each argument */
          462  +){
          463  +  BtCursor *pCur;
          464  +  int rc;
          465  +
          466  +  if( argc!=2 ){
          467  +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
          468  +       " ID\"", 0);
          469  +    return TCL_ERROR;
          470  +  }
          471  +  if( Tcl_GetInt(interp, argv[1], (int*)&pCur) ) return TCL_ERROR;
          472  +  rc = sqliteBtreeDelete(pCur);
          473  +  if( rc ){
          474  +    Tcl_AppendResult(interp, errorName(rc), 0);
          475  +    return TCL_ERROR;
          476  +  }
          477  +  return SQLITE_OK;
          478  +}
          479  +
          480  +/*
          481  +** Usage:   btree_insert ID KEY DATA
          482  +**
          483  +** Create a new entry with the given key and data.  If an entry already
          484  +** exists with the same key the old entry is overwritten.
          485  +*/
          486  +static int btree_insert(
          487  +  void *NotUsed,
          488  +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
          489  +  int argc,              /* Number of arguments */
          490  +  char **argv            /* Text of each argument */
          491  +){
          492  +  BtCursor *pCur;
          493  +  int rc;
          494  +
          495  +  if( argc!=4 ){
          496  +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
          497  +       " ID KEY DATA\"", 0);
          498  +    return TCL_ERROR;
          499  +  }
          500  +  if( Tcl_GetInt(interp, argv[1], (int*)&pCur) ) return TCL_ERROR;
          501  +  rc = sqliteBtreeInsert(pCur, argv[2], strlen(argv[2]),
          502  +                         argv[3], strlen(argv[3]));
          503  +  if( rc ){
          504  +    Tcl_AppendResult(interp, errorName(rc), 0);
          505  +    return TCL_ERROR;
          506  +  }
          507  +  return SQLITE_OK;
          508  +}
          509  +
          510  +/*
          511  +** Usage:   btree_next ID
          512  +**
          513  +** Move the cursor to the next entry in the table.
          514  +*/
          515  +static int btree_next(
          516  +  void *NotUsed,
          517  +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
          518  +  int argc,              /* Number of arguments */
          519  +  char **argv            /* Text of each argument */
          520  +){
          521  +  BtCursor *pCur;
          522  +  int rc;
          523  +
          524  +  if( argc!=2 ){
          525  +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
          526  +       " ID\"", 0);
          527  +    return TCL_ERROR;
          528  +  }
          529  +  if( Tcl_GetInt(interp, argv[1], (int*)&pCur) ) return TCL_ERROR;
          530  +  rc = sqliteBtreeNext(pCur, 0);
          531  +  if( rc ){
          532  +    Tcl_AppendResult(interp, errorName(rc), 0);
          533  +    return TCL_ERROR;
          534  +  }
          535  +  return SQLITE_OK;
          536  +}
          537  +
          538  +/*
          539  +** Usage:   btree_key ID
          540  +**
          541  +** Return the key for the entry at which the cursor is pointing.
          542  +*/
          543  +static int btree_key(
          544  +  void *NotUsed,
          545  +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
          546  +  int argc,              /* Number of arguments */
          547  +  char **argv            /* Text of each argument */
          548  +){
          549  +  BtCursor *pCur;
          550  +  int rc;
          551  +  int n;
          552  +  char *zBuf;
          553  +
          554  +  if( argc!=2 ){
          555  +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
          556  +       " ID\"", 0);
          557  +    return TCL_ERROR;
          558  +  }
          559  +  if( Tcl_GetInt(interp, argv[1], (int*)&pCur) ) return TCL_ERROR;
          560  +  sqliteBtreeKeySize(pCur, &n);
          561  +  zBuf = malloc( n+1 );
          562  +  rc = sqliteBtreeKey(pCur, 0, n, zBuf);
          563  +  if( rc ){
          564  +    free(zBuf);
          565  +    Tcl_AppendResult(interp, errorName(rc), 0);
          566  +    return TCL_ERROR;
          567  +  }
          568  +  zBuf[n] = 0;
          569  +  Tcl_AppendResult(interp, zBuf, 0);
          570  +  free(zBuf);
          571  +  return SQLITE_OK;
          572  +}
          573  +
          574  +/*
          575  +** Usage:   btree_data ID
          576  +**
          577  +** Return the data for the entry at which the cursor is pointing.
          578  +*/
          579  +static int btree_data(
          580  +  void *NotUsed,
          581  +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
          582  +  int argc,              /* Number of arguments */
          583  +  char **argv            /* Text of each argument */
          584  +){
          585  +  BtCursor *pCur;
          586  +  int rc;
          587  +  int n;
          588  +  char *zBuf;
          589  +
          590  +  if( argc!=2 ){
          591  +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
          592  +       " ID\"", 0);
          593  +    return TCL_ERROR;
          594  +  }
          595  +  if( Tcl_GetInt(interp, argv[1], (int*)&pCur) ) return TCL_ERROR;
          596  +  sqliteBtreeDataSize(pCur, &n);
          597  +  zBuf = malloc( n+1 );
          598  +  rc = sqliteBtreeData(pCur, 0, n, zBuf);
          599  +  if( rc ){
          600  +    free(zBuf);
          601  +    Tcl_AppendResult(interp, errorName(rc), 0);
          602  +    return TCL_ERROR;
          603  +  }
          604  +  zBuf[n] = 0;
          605  +  Tcl_AppendResult(interp, zBuf, 0);
          606  +  free(zBuf);
          607  +  return SQLITE_OK;
          608  +}
          609  +
          610  +/*
          611  +** Usage:   btree_cursor_dump ID
          612  +**
          613  +** Return two integers which are the page number and cell index for
          614  +** the given cursor.
          615  +*/
          616  +static int btree_cursor_dump(
          617  +  void *NotUsed,
          618  +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
          619  +  int argc,              /* Number of arguments */
          620  +  char **argv            /* Text of each argument */
          621  +){
          622  +  BtCursor *pCur;
          623  +  int rc;
          624  +  int aResult[2];
          625  +  char zBuf[50];
          626  +
          627  +  if( argc!=2 ){
          628  +    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
          629  +       " ID\"", 0);
          630  +    return TCL_ERROR;
          631  +  }
          632  +  if( Tcl_GetInt(interp, argv[1], (int*)&pCur) ) return TCL_ERROR;
          633  +  rc = sqliteBtreeCursorDump(pCur, aResult);
          634  +  if( rc ){
   254    635       Tcl_AppendResult(interp, errorName(rc), 0);
   255    636       return TCL_ERROR;
   256    637     }
   257         -  return TCL_OK;
          638  +  sprintf(zBuf,"%d %d",aResult[0], aResult[1]);
          639  +  Tcl_AppendResult(interp, zBuf, 0);
          640  +  return SQLITE_OK;
   258    641   }
   259    642   
   260    643   /*
   261    644   ** Register commands with the TCL interpreter.
   262    645   */
   263    646   int Sqlitetest3_Init(Tcl_Interp *interp){
   264    647     Tcl_CreateCommand(interp, "btree_open", btree_open, 0, 0);
................................................................................
   265    648     Tcl_CreateCommand(interp, "btree_close", btree_close, 0, 0);
   266    649     Tcl_CreateCommand(interp, "btree_begin_transaction",
   267    650         btree_begin_transaction, 0, 0);
   268    651     Tcl_CreateCommand(interp, "btree_commit", btree_commit, 0, 0);
   269    652     Tcl_CreateCommand(interp, "btree_rollback", btree_rollback, 0, 0);
   270    653     Tcl_CreateCommand(interp, "btree_create_table", btree_create_table, 0, 0);
   271    654     Tcl_CreateCommand(interp, "btree_drop_table", btree_drop_table, 0, 0);
          655  +  Tcl_CreateCommand(interp, "btree_get_meta", btree_get_meta, 0, 0);
          656  +  Tcl_CreateCommand(interp, "btree_update_meta", btree_update_meta, 0, 0);
          657  +  Tcl_CreateCommand(interp, "btree_page_dump", btree_page_dump, 0, 0);
          658  +  Tcl_CreateCommand(interp, "btree_cursor", btree_cursor, 0, 0);
          659  +  Tcl_CreateCommand(interp, "btree_close_cursor", btree_close_cursor, 0, 0);
          660  +  Tcl_CreateCommand(interp, "btree_move_to", btree_move_to, 0, 0);
          661  +  Tcl_CreateCommand(interp, "btree_delete", btree_delete, 0, 0);
          662  +  Tcl_CreateCommand(interp, "btree_insert", btree_insert, 0, 0);
          663  +  Tcl_CreateCommand(interp, "btree_next", btree_next, 0, 0);
          664  +  Tcl_CreateCommand(interp, "btree_key", btree_key, 0, 0);
          665  +  Tcl_CreateCommand(interp, "btree_data", btree_data, 0, 0);
          666  +  Tcl_CreateCommand(interp, "btree_cursor_dump", btree_cursor_dump, 0, 0);
   272    667     return TCL_OK;
   273    668   }