/ Check-in [1662063d]
Login

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

Overview
Comment::-) (CVS 178)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:1662063dfb0925bd439e3e2e49bff82705e20fd0
User & Date: drh 2001-01-20 19:52:49
Context
2001-01-21
00:58
:-) (CVS 179) check-in: d5f2a668 user: drh tags: trunk
2001-01-20
19:52
:-) (CVS 178) check-in: 1662063d user: drh tags: trunk
2001-01-15
22:51
continued progress toward version 2.0 (CVS 1710) check-in: a60af40a user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Added src/db.c.

            1  +/*
            2  +** Copyright (c) 2001 D. Richard Hipp
            3  +**
            4  +** This program is free software; you can redistribute it and/or
            5  +** modify it under the terms of the GNU General Public
            6  +** License as published by the Free Software Foundation; either
            7  +** version 2 of the License, or (at your option) any later version.
            8  +**
            9  +** This program is distributed in the hope that it will be useful,
           10  +** but WITHOUT ANY WARRANTY; without even the implied warranty of
           11  +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
           12  +** General Public License for more details.
           13  +** 
           14  +** You should have received a copy of the GNU General Public
           15  +** License along with this library; if not, write to the
           16  +** Free Software Foundation, Inc., 59 Temple Place - Suite 330,
           17  +** Boston, MA  02111-1307, USA.
           18  +**
           19  +** Author contact information:
           20  +**   drh@hwaci.com
           21  +**   http://www.hwaci.com/drh/
           22  +**
           23  +*************************************************************************
           24  +** $Id: db.c,v 1.1 2001/01/20 19:52:49 drh Exp $
           25  +*/
           26  +#include "sqliteInt.h"
           27  +#include "pg.h"
           28  +
           29  +/*
           30  +** Everything we need to know about an open database
           31  +*/
           32  +struct Db {
           33  +  Pgr *pPgr;            /* The pager for the database */
           34  +  DbCursor *pCursor;    /* All open cursors */
           35  +  int inTransaction;    /* True if a transaction is in progress */
           36  +  int nContents;        /* Number of slots in aContents[] */
           37  +  int nAlloc;           /* Space allocated for aContents[] */
           38  +  u32 *aContents;       /* Contents table for the database */
           39  +};
           40  +
           41  +/*
           42  +** The maximum depth of a cursor
           43  +*/
           44  +#define MX_LEVEL 10
           45  +
           46  +/*
           47  +** Within a cursor, each level off the search tree is an instance of
           48  +** this structure.
           49  +*/
           50  +typedef struct DbIdxpt DbIdxpt;
           51  +struct DbIdxpt {
           52  +  int pgno;         /* The page number */
           53  +  u32 *aPage;       /* The page data */
           54  +  int idx;          /* Index into pPage[] */
           55  +};
           56  +
           57  +/*
           58  +** Everything we need to know about a cursor
           59  +*/
           60  +struct DbCursor {
           61  +  Db *pDb;                      /* The whole database */
           62  +  DbCursor *pPrev, *pNext;      /* Linked list of all cursors */
           63  +  u32 rootPgno;                 /* Root page of table for this cursor */
           64  +  int onEntry;                  /* True if pointing to a table entry */
           65  +  int nLevel;                   /* Number of levels of indexing used */
           66  +  DbIdxpt aLevel[MX_LEVEL];     /* The index levels */
           67  +};
           68  +
           69  +/*
           70  +** The first word of every page is some combination of these values
           71  +** used to indicate its function.
           72  +*/
           73  +#define BLOCK_MAGIC            0x24e47190
           74  +#define BLOCK_INDEX            0x00000001
           75  +#define BLOCK_LEAF             0x00000002
           76  +#define BLOCK_FREE             0x00000003
           77  +#define BLOCK_OVERFLOW         0x00000004
           78  +#define BLOCK_CONTENTS         0x00000005
           79  +#define BLOCK_MAGIC_MASK       0xfffffff8
           80  +#define BLOCK_TYPE_MASK        0x00000007
           81  +
           82  +/*
           83  +** Free blocks:
           84  +**
           85  +**     0.   BLOCK_MAGIC | BLOCK_FREE
           86  +**     1.   address of next block on freelist
           87  +**
           88  +** Leaf blocks:
           89  +**
           90  +**     0.   BLOCK_MAGIC | BLOCK_LEAF 
           91  +**     1.   number of table entries  (only used if a table root block)
           92  +**     entries....
           93  +**         0.  size of this entry (measured in u32's)
           94  +**         1.  hash
           95  +**         2.  keysize  (in bytes. bit 31 set if uses overflow)
           96  +**         3.  datasize (in bytes. bit 31 set if uses overflow pages)
           97  +**         4.  key
           98  +**         5+. data
           99  +**
          100  +** Overflow block:
          101  +**
          102  +**     0.   BLOCK_MAGIC | BLOCK_OVERFLOW
          103  +**     1.   address of next block in overflow buffer
          104  +**     data...
          105  +**
          106  +** Index block:
          107  +**
          108  +**     0.   BLOCK_MAGIC | BLOCK_INDEX
          109  +**     1.   number of table entries  (only used if a table root block)
          110  +**     2.   entries in this index block
          111  +**     entries...
          112  +**         0.  largest hash value for pgno
          113  +**         1.  pgno of subblock
          114  +**
          115  +** Contents block:  (The first page in the file)
          116  +**     0.   BLOCK_MAGIC | BLOCK_CONTENTS
          117  +**     1.   overflow page list
          118  +**     2.   freelist
          119  +**     3.   number of tables
          120  +**     table root page numbers...
          121  +*/
          122  +
          123  +/*
          124  +** Byte swapping code.
          125  +*/
          126  +#ifdef BIG_ENDIAN
          127  +# SWB(x) (x)
          128  +#else
          129  +# SWB(x) sqliteDbSwapBytes(x)
          130  +#endif
          131  +
          132  +static u32 sqliteDbSwapBytes(u32 x){
          133  +  unsigned char c, *s, *d;
          134  +  s = (unsigned char*)&x;
          135  +  d = (unsigned char*)&r;
          136  +  d[0] = s[3];
          137  +  d[1] = s[2];
          138  +  d[2] = s[1];
          139  +  d[3] = s[0];
          140  +  return r;
          141  +}
          142  +
          143  +#endif
          144  +
          145  +/*
          146  +** Allocate space for the content table in the given Db structure.
          147  +** return SQLITE_OK on success and SQLITE_NOMEM if it fails.
          148  +*/
          149  +static int sqliteDbExpandContent(Db *pDb, int newSize){
          150  +  if( pDb->nAlloc>=newSize ) return SQLITE_OK;
          151  +  pDb->nAlloc = newSize;
          152  +  pDb->aContent = sqliteRealloc( pDb->aContent, pDb->nAlloc*sizeof(u32));
          153  +  if( pDb->aContent==0 ){
          154  +    pDb->nContent = 0;
          155  +    pDb->nAlloc = 0;
          156  +    pDb->inTranaction = 0;
          157  +    return SQLITE_NOMEM;
          158  +  }
          159  +  return SQLITE_OK;
          160  +}
          161  +
          162  +/*
          163  +** Allocate a new page.  Return both the page number and a pointer
          164  +** to the page data.  The calling function is responsible for unref-ing
          165  +** the page when it is no longer needed.
          166  +*/
          167  +int sqliteDbAllocPage(Db *pDb, u32 *pPgno, u32 **ppPage){
          168  +  u32 pgno;
          169  +  int rc;
          170  +
          171  +  if( pDb->aContent==0 ) return SQLITE_NOMEM;
          172  +  pgno = SWB(pDb->aContent[0]);
          173  +  if( pgno!=0 ){
          174  +    rc = sqlitePgGet(pDb->pPgr, pgno, (void**)ppPage);
          175  +    if( rc==SQLITE_OK ){
          176  +      pDb->aContent[0] = pFree[1];
          177  +      *pPgno = pgno;
          178  +      return SQLITE_OK;
          179  +    }
          180  +  }
          181  +  if( (rc = sqlitePgAlloc(pDb->pPgr, &pgno))==SQLITE_OK &&
          182  +      (rc = sqlitePgGet(pDb->pPgr, pgno, (void**)ppPage))==SQLITE_OK ){
          183  +    *pPgno = pgno;
          184  +    return SQLITE_OK;
          185  +  }
          186  +  return rc;
          187  +}
          188  +
          189  +/*
          190  +** Return a page to the freelist and dereference the page.
          191  +*/
          192  +static void sqliteDbFreePage(DB *pDb, u32 pgno, u32 *aPage){
          193  +  if( pDb->aContent==0 ) return;
          194  +  aPage[0] = SWB(BLOCK_MAGIC | BLOCK_FREE);
          195  +  aPage[1] = pDb->aContent[0];
          196  +  memset(&aPage[2], 0, SQLITE_PAGE_SIZE - 2*sizeof(u32));
          197  +  pDb->aContent[0] = SWB(pgno);
          198  +  sqlitePgTouch(aPage);
          199  +  sqlitePgUnref(aPage);
          200  +}
          201  +
          202  +/*
          203  +** Open a database.
          204  +*/
          205  +int sqliteDbOpen(const char *filename, Db **ppDb){
          206  +  Db *pDb = 0;
          207  +  Pgr *pPgr = 0;
          208  +  u32 *aPage1;
          209  +  int rc;
          210  +
          211  +  rc = sqlitePgOpen(filename, &pPgr);
          212  +  if( rc!=SQLITE_OK ) goto open_err;
          213  +  pDb = sqliteMalloc( sizeof(*pDb) );
          214  +  if( pDb==0 ){
          215  +    rc = SQLITE_NOMEM;
          216  +    goto open_err;
          217  +  }
          218  +  pDb->pPgr = pPgr;
          219  +  pDb->pCursor = 0;
          220  +  pDb->inTransaction = 0;
          221  +  rc = sqlitePgGet(pDb->pPgr, 1, &aPage1);
          222  +  if( rc!=0 ) goto open_err;
          223  +  pDb->nContent = SWB(aPage1[3]) + 2;
          224  +  pDb->nAlloc = 0;
          225  +  rc = sqliteDbExpandContent(pDb, pDb->nContent);
          226  +  if( rc!=SQLITE_OK ) goto open_err;
          227  +  rc = sqliteDbReadOvfl(pDb, 1, aPage1, 0, pDb->nContent*sizeof(u32),
          228  +                        pDb->aContent);
          229  +  if( rc!=SQLITE_OK ) goto open_err;
          230  +  sqlitePgUnref(aPage1);
          231  +  *ppDb = pDb;
          232  +  return SQLITE_OK;
          233  +
          234  +open_err:
          235  +  *ppDb = 0;
          236  +  if( pPgr ) sqlitePgClose(pPgr);
          237  +  if( pDb && pDb->aContent ) sqliteFree(pDb->aContent);
          238  +  if( pDb ) sqliteFree(pDb);
          239  +  return rc;
          240  +}
          241  +
          242  +/*
          243  +** Close a database
          244  +*/
          245  +int sqliteDbClose(Db *pDb){
          246  +  while( pDb->pCursor ){
          247  +    sqliteDbCursorClose(pDb->pCursor);
          248  +  }
          249  +  sqlitePgClose(pDb->pPgr);
          250  +  sqliteFree(pDb->aContent);
          251  +  sqliteFree(pDb);
          252  +  return SQLITE_OK;
          253  +}
          254  +
          255  +/*
          256  +** Begin a transaction
          257  +*/
          258  +int sqliteDbBeginTransaction(Db *pDb){
          259  +  int rc;
          260  +  if( pDb->aContent==0 ){
          261  +    return SQLITE_NOMEM;
          262  +  }
          263  +  if( pDb->inTransaction ){
          264  +    return SQLITE_INTERNAL;
          265  +  }
          266  +  rc = sqlitePgBeginTransaction(pDb->pPgr);
          267  +  if( rc!=SQLITE_OK ){
          268  +    return rc;
          269  +  }
          270  +  pDb->inTransaction = 1;
          271  +  return SQLITE_OK;
          272  +}
          273  +
          274  +/*
          275  +** Commit changes to the database
          276  +*/ 
          277  +int sqliteDbCommit(Db *pDb){
          278  +  if( !pDb->inTransaction ){
          279  +    return SQLITE_OK;
          280  +  }
          281  +  sqliteDbWriteOvfl(pDb, 1, 0, pDb->nContent*sizeof(u32), pDb->aContent);
          282  +  rc = sqlitePgCommit(pDb->pPgr);
          283  +  if( rc!=SQLITE_OK ) return rc;
          284  +  pDb->inTransaction = 0;
          285  +  return SQLITE_OK;
          286  +}
          287  +
          288  +/*
          289  +** Rollback the database to its state prior to the beginning of
          290  +** the transaction
          291  +*/
          292  +int sqliteDbRollback(Db *pDb){
          293  +  u32 *aPage1;
          294  +  if( !pDb->inTransaction ) return SQLITE_OK;
          295  +  rc = sqlitePgRollback(pDb->pPgr);
          296  +  if( rc!=SQLITE_OK ) return rc;
          297  +  rc = sqlitePgGet(pDb->pPgr, 1, &aPage1);
          298  +  if( rc!=SQLITE_OK ) return rc;
          299  +  pDb->nContent = SWB(aPage1[3]) + 2;
          300  +  if( sqliteDbExpandContent(pDb, pDb->nContent)!=SQLITE_OK ){
          301  +    return SQLITE_NOMEM;
          302  +  }
          303  +  sqliteDbReadOvfl(pDb, 1, aPage1, 0, pDb->nContent*sizeof(u32), pDb->aContent);
          304  +  pDb->inTransaction = 0;
          305  +  return SQLITE_OK;
          306  +}
          307  +
          308  +/*
          309  +** Create a new table in the database.  Write the table number
          310  +** that is used to open a cursor into that table into *pTblno.
          311  +*/
          312  +int sqliteDbCreateTable(Db *pDb, int *pTblno){
          313  +  u32 *pPage;
          314  +  u32 pgno;
          315  +  int rc;
          316  +  int swTblno;
          317  +  int i;
          318  +
          319  +  rc = sqliteDbAllocPage(pDb, &pgno, &pPage);
          320  +  if( rc!=SQLITE_OK ){
          321  +    return rc;
          322  +  }
          323  +  tblno = -1;
          324  +  for(i=2; i<pDb->nContent; i++){
          325  +    if( pDb->aContent[i]==0 ){
          326  +      tblno = i - 2;
          327  +      break;
          328  +    }
          329  +  }
          330  +  if( tblno<0 ){
          331  +    tblno = SWB(pDb->aContent[1]);
          332  +  }
          333  +  if( tblno+2 >= pDb->nContent ){
          334  +    sqliteDbExpandContent(pDb, tblno+2);
          335  +  }
          336  +  if( pDb->aContent==0 ){
          337  +    return SQLITE_NOMEM;
          338  +  }
          339  +  pDb->aContent[tblno+2] = SWB(pgno);
          340  +  pPage[0] = SWB(BLOCK_MAGIC | BLOCK_LEAF);
          341  +  memset(&pPage[1], 0, SQLITE_PAGE_SIZE - sizeof(u32));
          342  +  sqlitePgTouch(pPage);
          343  +  sqlitePgUnref(pPage);
          344  +  return SQLITE_OK;
          345  +}
          346  +
          347  +/* forward reference */
          348  +static int sqliteDbClearEntry(Db *pDb, u32 *pEntry);
          349  +
          350  +/*
          351  +** Recursively add a page to the free list
          352  +*/
          353  +static int sqliteDbDropPage(Db *pDb, u32 pgno){
          354  +  u32 *aPage;
          355  +  int rc;
          356  +
          357  +  rc = sqlitePgGet(pDb->pPgr, pgno, (void**)&aPage);
          358  +  if( rc!=SQLITE_OK ) return rc;
          359  +  switch(  SWB(aPage[0]) ){
          360  +    case BLOCK_MAGIC | BLOCK_INDEX: {
          361  +      int n, i;
          362  +      n = SWB(aPage[2]);
          363  +      for(i=0; i<n; i++){
          364  +        u32 subpgno = SWB(aPage[3+i*2]);
          365  +        sqliteDbDropPage(pDb, subpgno);
          366  +      }
          367  +      sqliteDbFreePage(pDb, pgno, aPage);
          368  +      break;
          369  +    }
          370  +    case BLOCK_MAGIC | BLOCK_LEAF: {
          371  +      int i = 1;
          372  +      while( i<SQLITE_PAGE_SIZE/sizeof(u32) ){
          373  +        int entrySize = SWB(aPage[i]);
          374  +        if( entrySize==0 ) break;
          375  +        sqliteDbClearEntry(pDb, &aPage[i]);
          376  +        i += entrySize;
          377  +      }
          378  +      sqliteDbFreePage(pDb, pgno, aPage);
          379  +      break;
          380  +    }
          381  +    case BLOCK_MAGIC | BLOCK_OVERFLOW: {
          382  +      for(;;){
          383  +        u32 nx = SWB(aPage[1]);
          384  +        sqliteDbFreePage(pDb, pgno, aPage);
          385  +        if( nx==0 ) break;
          386  +        pgno = nx;
          387  +        sqlitePgUnref(aPage);
          388  +        sqlitePgGet(pDb->pPgr, pgno, &aPage);
          389  +      }
          390  +      break;
          391  +    }
          392  +    default: {
          393  +      /* Do nothing */
          394  +      break;
          395  +    }
          396  +  }
          397  +}
          398  +
          399  +/*
          400  +** aEntry points directly at a database entry on a leaf page.
          401  +** Free any overflow pages associated with the key or data of
          402  +** this entry.
          403  +*/
          404  +static int sqliteDbClearEntry(Db *pDb, u32 *aEntry){
          405  +  int nByte;
          406  +  int idx;
          407  +
          408  +  idx = 4;
          409  +  nByte = SWB(aEntry[2]);
          410  +  if( nByte & 0x80000000 ){
          411  +    sqliteDbDropPage(pDb, SWB(aEntry[idx]));
          412  +    idx++;
          413  +  }else{
          414  +    idx += (nByte + 3)/4;
          415  +  }
          416  +  nByte = SWB(aEntry[3]);
          417  +  if( nByte & 0x80000000 ){
          418  +    sqliteDbDropPage(pDb, SWB(aEntry[idx]));
          419  +  }
          420  +  return SQLITE_OK;
          421  +}
          422  +
          423  +/*
          424  +** Delete the current associate of a cursor and release all the
          425  +** pages it holds.  Except, do not release pages at levels less
          426  +** than N.
          427  +*/
          428  +static void sqliteDbResetCursor(DbCursor *pCur, int N){
          429  +  int i;
          430  +  for(i=pCur->nLevel-1; i>=N; i--){
          431  +    sqlitePgUnref(pCur->aLevel[i].aPage);
          432  +  }
          433  +  pCur->nLevel = N;
          434  +  pCur->onEntry = 0;
          435  +}
          436  +
          437  +/*
          438  +** Delete an entire table.
          439  +*/
          440  +static int sqliteDbDropTable(Db *pDb, int tblno){
          441  +  DbCursor *pCur;
          442  +  u32 pgno;
          443  +
          444  +  /* Find the root page for the table to be dropped.
          445  +  */
          446  +  if( pDb->aContent==0 ){
          447  +    return SQLITE_NOMEM;
          448  +  }
          449  +  if( tblno<0 || tblno+2>=pDb->nContent || pDb->aContent[tblno+2]==0 ){
          450  +    return SQLITE_NOTFOUND;
          451  +  }
          452  +  pgno = SWB(pDb->aContent[tblno+2]);
          453  +
          454  +  /* Reset any cursors point to the table that is about to
          455  +  ** be dropped */
          456  +  for(pCur=pDb->pCursor; pCur; pCur=pCur->pNext){
          457  +    if( pCur->rootPgno==pgno ){
          458  +      sqliteDbResetCursor(pCur, 0);
          459  +    }
          460  +  }
          461  +
          462  +  /* Move all pages associated with this table to the freelist
          463  +  */
          464  +  sqliteDbDropPage(pDb, pgno);
          465  +  return SQLITE_OK;
          466  +}
          467  +
          468  +/*
          469  +** Create a new cursor
          470  +*/
          471  +int sqliteDbCursorOpen(Db *pDb, int tblno, DbCursor **ppCur){
          472  +  u32 pgno;
          473  +  DbCursor *pCur;
          474  +
          475  +  /* Translate the table number into a page number
          476  +  */
          477  +  if( pDb->aContent==0 ){
          478  +    *ppCur = 0;
          479  +    return SQLITE_NOMEM;
          480  +  }
          481  +  if( tblno<0 || tblno+2>=pDb->nContent || pDb->aContent[tblno+2]==0 ){
          482  +    *ppCur = 0;
          483  +    return SQLITE_NOTFOUND;
          484  +  }
          485  +  pgno = SWB(pDb->aContent[tblno+2]);
          486  +  
          487  +  /* Allocate the cursor
          488  +  */
          489  +  pCur = sqliteMalloc( sizeof(*pCur) );
          490  +  pCur->pgno = pgno;
          491  +  pCur->pDb = pDb;
          492  +  pCur->pNext = pDb->pCursor;
          493  +  pCur->pPrev = 0;
          494  +  if( pDb->pCursor ){
          495  +     pDb->pCursor->pPrev = pCur;
          496  +  }
          497  +  pDb->pCursor = pCur;
          498  +  *ppCur = pCur;
          499  +  return SQLITE_OK;
          500  +}
          501  +
          502  +/*
          503  +** Delete a cursor
          504  +*/
          505  +int sqliteDbCursorClose(DbCursor *pCur){
          506  +  int i;
          507  +  if( pCur->pPrev ){
          508  +    pCur->pPrev->pNext = pCur->pNext;
          509  +  }else if( pCur->pDb->pCursor==pCur ){
          510  +    pCur->pDb->pCursor = pCur->pNext;
          511  +  }
          512  +  if( pCur->pNext ){
          513  +    pCur->pNext->pPrev = pCur->pPrev;
          514  +  }
          515  +  sqliteDbResetCursor(pCur, 0);
          516  +  sqliteFree(pCur);
          517  +  return SQLITE_OK; 
          518  +}
          519  +
          520  +/*
          521  +** Beginning at index level "i" (the outer most index is 0), move down 
          522  +** to the first entry of the table.  Levels above i (less than i) are 
          523  +** unchanged.
          524  +*/
          525  +static int sqliteDbGotoFirst(DbCursor *pCur, int i){
          526  +  int rc = -1;
          527  +
          528  +  assert( i>=0 && i<MAX_LEVEL );
          529  +  if( pCur->nLevel > i+1 ){
          530  +    sqliteDbResetCursor(pCur, i+1);
          531  +  }
          532  +  assert( pCur->nLevel==i+1 );
          533  +  while( rc < 0 ){
          534  +    u32 *aPage = pCur->aLevel[i].aPage;
          535  +    assert( aPage!=0 );
          536  +    switch( SWB(aPage[0]) ){
          537  +      case BLOCK_LEAF | BLOCK_MAGIC: {
          538  +        if( aPage[1]!=0 ){
          539  +          pCur->aLevel[i].idx = 1;
          540  +          pCur->onEntry = 1;
          541  +        }else{
          542  +          sqliteDbResetCursor(pCur, 1);
          543  +        }
          544  +        rc = SQLITE_OK;
          545  +        break;
          546  +      }
          547  +      case BLOCK_INDEX | BLOCK_MAGIC: {
          548  +        int n = SWB(aPage[2]);
          549  +        if( n<2 || n>=((SQLITE_PAGE_SIZE/sizeof(u32))-3)/2 ){
          550  +          sqliteDbResetCur(pCur, 1);
          551  +          rc = SQLITE_CORRUPT;
          552  +          break;
          553  +        }
          554  +        pCur->nLevel++;
          555  +        i++;
          556  +        pCur->aLevel[i].pgno = SWB(aPage[4]);
          557  +        rc = sqlitePgGet(pCur->pDb->pPgr, pCur->aLevel[i].pgno,
          558  +                    &pCur->aLevel[i].aPage);
          559  +        if( rc != SQLITE_OK ){
          560  +          sqliteDbResetCursor(pCur, 1);
          561  +        }else{
          562  +          rc = -1;
          563  +        }
          564  +        break;
          565  +      }
          566  +      default: {
          567  +        sqliteDbResetCursor(pCur, 1);
          568  +        rc = SQLITE_CORRUPT;
          569  +      }
          570  +    }
          571  +  }
          572  +  return rc;
          573  +}
          574  +
          575  +/*
          576  +** Move the cursor to the first entry in the table.
          577  +*/
          578  +int sqliteDbCursorFirst(DbCursor *pCur){
          579  +  if( pCur->nLevel==0 ){
          580  +    int rc;
          581  +    pCur->aLevel[0].pgno = pCur->rootPgno;
          582  +    rc = sqlitePgGet(pCur->pDb->pPgr, pCur->rootPgno, pCur->aLevel[0].aPage);
          583  +    if( rc!=SQLITE_OK ){
          584  +      sqliteDbResetCursor(pCur, 0);
          585  +      return rc;
          586  +    }
          587  +    pCur->nLevel = 1;
          588  +  }
          589  +  return sqliteDbGotoFirst(pCur, 0);
          590  +}
          591  +
          592  +/*
          593  +** Advance the cursor to the next entry in the table.
          594  +*/
          595  +int sqliteDbCursorNext(DbCursor *pCur){
          596  +  int i, idx, n, rc;
          597  +  u32 pgno, *aPage;
          598  +  if( !pCur->onEntry ){
          599  +     return sqliteDbCursorFirst(pCur);
          600  +  }
          601  +  i = pCur->nLevel-1;
          602  +  aPage = pCur->aLevel[i].aPage;
          603  +  idx = pCur->aLevel[i].idx;
          604  +  idx += SWB(aPage[idx]);
          605  +  if( idx >= SQLITE_PAGE_SIZE/sizeof(u32) ){
          606  +    sqliteDbResetCursor(pCur, 1);
          607  +    return SQLITE_CORRUPT;
          608  +  }
          609  +  if( aPage[idx]!=0 ){
          610  +    pCur->aLabel[i].idx = idx;
          611  +    return SQLITE_OK;
          612  +  }
          613  +  rc = SQLITE_OK;
          614  +  while( pCur->nLevel>1 ){
          615  +    pCur->nLevel--;
          616  +    i = pCur->nLevel-1;
          617  +    sqlitePgUnref(pCur->aLevel[pCur->nLevel].aPage);
          618  +    aPage = pCur->aLevel[i].aPage;
          619  +    idx = pCur->aLevel[i].idx;
          620  +    assert( SWB(aPage[0])==BLOCK_MAGIC|BLOCK_INDEX );
          621  +    n = SWB(aPage[2]);
          622  +    idx += 2;
          623  +    if( (idx-3)/2 < n ){
          624  +      pCur->aLevel[i].idx = idx;
          625  +      pCur->nLevel++;
          626  +      i++;
          627  +      pgno = pCur->aLevel[i].pgno = SWB(aPage[idx+1]);
          628  +      rc = sqlitePgGet(pDb->pPgr, pgno, &pCur->aLevel[i].aPage);
          629  +      if( rc!=SQLITE_OK ) break;
          630  +      rc = sqliteDbGotoFirst(pCur, i);
          631  +      break;
          632  +    }
          633  +  }
          634  +  sqliteDbResetCursor(pCur, 0);
          635  +  return SQLITE_OK;
          636  +}
          637  +
          638  +/*
          639  +** Return the amount of data on the entry that the cursor points
          640  +** to.
          641  +*/
          642  +int sqliteDbCursorDatasize(DbCursor *pCur){
          643  +  u32 *aPage;
          644  +  int idx, i;
          645  +  if( !pCur->onEntry ) return 0;
          646  +  i = pCur->nLevel-1;
          647  +  idx = pCur->aLevel[i].idx;
          648  +  aPage = pCur->aLevel[i].aPage;
          649  +  assert( aPage );
          650  +  assert( idx>=2 && idx+4<(SQLITE_PAGE_SIZE/sizeof(u32))
          651  +  return SWB(aPage[idx+3]) & 0x80000000;
          652  +}
          653  +
          654  +/*
          655  +** Return the number of bytes of key on the entry that the cursor points
          656  +** to.
          657  +*/
          658  +int sqliteDbCursorKeysize(DbCursor *pCur){
          659  +  u32 *aPage;
          660  +  int idx, i;
          661  +  if( !pCur->onEntry ) return 0;
          662  +  i = pCur->nLevel-1;
          663  +  idx = pCur->aLevel[i].idx;
          664  +  aPage = pCur->aLevel[i].aPage;
          665  +  assert( aPage );
          666  +  assert( idx>=2 && idx+4<(SQLITE_PAGE_SIZE/sizeof(u32))
          667  +  return SWB(aPage[idx+2]) & 0x80000000;
          668  +}
          669  +
          670  +/*
          671  +** Read data from the cursor.
          672  +*/
          673  +int sqliteDbCursorRead(DbCursor *pCur, int amt, int offset, void *buf){
          674  +  u32 *aPage;
          675  +  int idx, i, dstart;
          676  +  int nData;
          677  +  int nKey;
          678  +  char *cbuf = buf;
          679  +  char *cfrom;
          680  +  if( !pCur->onEntry ){
          681  +    memset(cbuf, 0, amt);
          682  +    return SQLITE_OK;
          683  +  }
          684  +  if( amt<=0 || offset<0 ){
          685  +    return SQLITE_ERR;
          686  +  }
          687  +  i = pCur->nLevel-1;
          688  +  idx = pCur->aLevel[i].idx;
          689  +  aPage = pCur->aLevel[i].aPage;
          690  +  assert( aPage );
          691  +  assert( idx>=2 && idx+4<(SQLITE_PAGE_SIZE/sizeof(u32))
          692  +  nData = SWB(aPage[idx+3]);
          693  +  nKey = SWB(aPage[idx+2]);
          694  +  dstart = idx + 4;
          695  +  if( nKey!=4 ) dstart++;
          696  +  if( nData & 0x80000000 ){
          697  +    return sqliteDbReadOvfl(pCur->pDb, SWB(aPage[dstart]), 0, amt, offset, buf);
          698  +  }
          699  +  cfrom = (char*)&aPage[dstart];
          700  +  cfrom += offset;
          701  +  nData -= offset;
          702  +  if( nData<0 ) nData = 0;
          703  +  if( amt>nData ){
          704  +    memset(&cbuf[nData], 0, amt-nData);
          705  +  }
          706  +  if( amt<nData ){
          707  +    nData = amt;
          708  +  }
          709  +  memcpy(cbuf, cfrom, nData);
          710  +}
          711  +
          712  +/*
          713  +** Read the current key from the cursor.
          714  +*/
          715  +int sqliteDbCursorReadKey(DbCursor *pCur, int amt, int offset, void *buf){
          716  +  u32 *aPage;
          717  +  int idx, i, kstart;
          718  +  int nData;
          719  +  int nKey;
          720  +  char *cbuf = buf;
          721  +  char *cfrom;
          722  +  if( !pCur->onEntry ){
          723  +    memset(cbuf, 0, amt);
          724  +    return SQLITE_OK;
          725  +  }
          726  +  if( amt<=0 || offset<0 ){
          727  +    return SQLITE_ERR;
          728  +  }
          729  +  i = pCur->nLevel-1;
          730  +  idx = pCur->aLevel[i].idx;
          731  +  aPage = pCur->aLevel[i].aPage;
          732  +  assert( aPage );
          733  +  assert( idx>=2 && idx+4<(SQLITE_PAGE_SIZE/sizeof(u32))
          734  +  nKey = SWB(aPage[idx+2]);
          735  +  if( nKey & 0x80000000 ){  ############### -v
          736  +    return sqliteDbReadOvfl(pCur->pDb, SWB(aPage[idx+4]), 0, amt, offset, buf);
          737  +  }
          738  +  if( nKey==4 ){
          739  +    kstart = idx + 1;
          740  +  }else{
          741  +    kstart = idx + 4;
          742  +  }
          743  +  cfrom = (char*)&aPage[kstart];
          744  +  cfrom += offset;
          745  +  nKey -= offset;
          746  +  if( nKey<0 ) nKey = 0;
          747  +  if( amt>nKey ){
          748  +    memset(&cbuf[nKey], 0, amt-nKey);
          749  +  }
          750  +  if( amt<nKey ){
          751  +    nData = amt;
          752  +  }
          753  +  memcpy(cbuf, cfrom, nKey);
          754  +}
          755  +
          756  +/*
          757  +** Generate a 32-bit hash from the given key.
          758  +*/
          759  +static u32 sqliteDbHash(int nKey, void *pKey){
          760  +  u32 h;
          761  +  unsigned char *key;
          762  +  if( nKey==4 ){
          763  +    return *(u32*)pKey;
          764  +  }
          765  +  key = pKey;
          766  +  h = 0;
          767  +  while( 0 < nKey-- ){
          768  +    h = (h<<13) ^ (h<<3) ^ h ^ *(key++)
          769  +  }
          770  +  return h;
          771  +}
          772  +
          773  +/*
          774  +** Move the cursor so that the lowest level is the leaf page that
          775  +** contains (or might contain) the given key.
          776  +*/
          777  +static int sqliteDbFindLeaf(DbCursor *pCur, int nKey, void *pKey, u32 h;){
          778  +  int i, j, rc;
          779  +  u32 h;
          780  +
          781  +  h = sqliteDbHash(nKey, pKey);
          782  +  sqliteDbResetCursor(pCur, 1);
          783  +  i = 0;
          784  +  for(;;){
          785  +    u32 nxPgno;
          786  +    u32 *aPage = pCur->aLevel[i].aPage;
          787  +    if( SWB(aPage[0])==BLOCK_MAGIC|BLOCK_LEAF ) break;
          788  +    if( SWB(aPage[0])!=BLOCK_MAGIC|BLOCK_INDEX ){
          789  +      return SQLITE_CORRUPT;
          790  +    }
          791  +    if( i==MAX_LEVEL-1 ){
          792  +      return SQLITE_FULL;
          793  +    }
          794  +    n = SWB(aPage[2]);
          795  +    if( n<2 || n>=(SQLITE_PAGE_SIZE/2*sizeof(u32))-2 ){
          796  +      return SQLITE_CORRUPT;
          797  +    }
          798  +    for(j=0; j<n-1; j++){
          799  +      if( h < SWB(aPage[j*2+3]) ) break;
          800  +    }
          801  +    nxPgno = SWB(aPage[j*2+4]);
          802  +    pCur->aLevel[i].idx = j;
          803  +    pCur->aLevel[i].pgno = nxPgno;
          804  +    rc = sqlitePgGet(pCur->pDb->pPgr, nxPgno, &pCur->aLevel[i].aPage);
          805  +    if( rc!=SQLITE_OK ){
          806  +      return rc;
          807  +    }
          808  +    pCur->nLevel++;
          809  +    i++;
          810  +  }
          811  +  return SQLITE_OK;
          812  +}
          813  +
          814  +/*
          815  +** Position the cursor on the entry that matches the given key.
          816  +*/
          817  +int sqliteDbCursorMoveTo(DbCursor *pCur, int nKey, void *pKey){
          818  +  int rc, i;
          819  +  u32 *aPage;
          820  +  int idx;
          821  +  u32 h;
          822  +
          823  +  h = sqliteDbHash(nKey, pKey);
          824  +  rc = sqliteDbFindLeaf(pCur, nKey, pKey, h);
          825  +  if( rc!=SQLITE_OK ) return rc;
          826  +  i = pCur->nLevel-1;
          827  +  aPage = pCur->aLevel[i].aPage;
          828  +  idx = 2;
          829  +  rc = SQLITE_NOTFOUND;
          830  +  while( idx>=2 && idx<(SQLITE_PAGE_SIZE/sizeof(u32))-3 && aPage[idx]!=0 ){
          831  +    if( sqliteDbKeyMatch(&aPage[idx], nKey, pKey, h) ){
          832  +      pCur->aLevel[i].idx = idx;
          833  +      pCur->onEntry = 1;
          834  +      rc = SQLITE_OK;
          835  +      break;
          836  +    }
          837  +    idx += SWB(aPage[idx]);
          838  +  }
          839  +  return rc;
          840  +}
          841  +
          842  +/*
          843  +** Insert a new entry into the table.  The cursor is left pointing at
          844  +** the new entry.
          845  +*/
          846  +int sqliteDbCursorInsert(   
          847  +   DbCursor *pCur,          /* A cursor on the table in which to insert */
          848  +   int nKey, void *pKey,    /* The insertion key */
          849  +   int nData, void *pData   /* The data to be inserted */
          850  +){
          851  +  int minNeeded, maxNeeded;    /* In u32-sized objects */
          852  +  int rc;
          853  +  u32 h;
          854  +  int available;
          855  +  int i, j, k;
          856  +  int nKeyU, nDataU;
          857  +  u32 *aPage;
          858  +  int incr = 1;
          859  +
          860  +  /* Null data is the same as a delete.
          861  +  */
          862  +  if( nData<=0 || pData==0 ){
          863  +    if( sqliteDbCursorMoveTo(pCur, nKey, pKey);
          864  +      return sqliteDbCursorDelete(pCur);
          865  +    }else{
          866  +      return SQLITE_OK;
          867  +    }
          868  +  }
          869  +
          870  +  /* Figure out how much free space is needed on a leaf block in order
          871  +  ** to hold the new record.
          872  +  */
          873  +  minNeeded = maxNeeded = 6;
          874  +  nKeyU = (nKey+3)/4;
          875  +  nDataU = (nData+3)/4;
          876  +  if( nKeyU + maxNeeded + 2 <= SQLITE_PAGE_SIZE/sizeof(u32) ){
          877  +    maxNeeded += nKeyU;
          878  +  }
          879  +  if( nKeyU < SQLITE_PAGE_SIZE/(3*sizeof(u32)) ){
          880  +    minNeeded += nKeyU;
          881  +  }
          882  +  if( nDataU + maxNeeded + 2 <= SQLITE_PAGE_SIZE/sizeof(u32) ){
          883  +    maxNeeded += nDataU
          884  +  }
          885  +  if( nDataU < SQLITE_PAGE_SIZE/(3*sizeof(u32)) ){
          886  +    minNeeded += nDataU;
          887  +  }
          888  +
          889  +  /* Move the cursor to the leaf block where the new record will be
          890  +  ** inserted.
          891  +  */
          892  +  h = sqliteDbHash(nKey, pKey);
          893  +  rc = sqliteDbFindLeaf(pCur, nKey, pKey, h);
          894  +  if( rc!=SQLITE_OK ) return rc;
          895  +
          896  +  /* Walk thru the leaf once and do two things:
          897  +  **   1.  Remove any prior entry with the same key.
          898  +  **   2.  Figure out how much space is available on this leaf.
          899  +  */
          900  +  i = j = 2;
          901  +  aPage = pCur->aLevel[pCur->nLevel-1].aPage;
          902  +  for(;;){
          903  +    int entrySize = SWB(aPage[i]);
          904  +    if( entrySize<=0 || entrySize + i >= SQLITE_PAGE_SIZE/sizeof(u32) ) break;
          905  +    if( !sqliteDbKeyMatch(&aPage[i], nKey, pKey, h) ){
          906  +      if( j<i ){
          907  +        for(k=0; k<entrySize; k++){
          908  +           aPage[j+k] = aPage[i+k];
          909  +        }
          910  +      }
          911  +      j += entrySize;
          912  +    }else{
          913  +      sqliteDbClearEntry(pCur->pDb, &aPage[i]);
          914  +      incr--;
          915  +    }
          916  +    i += entrySize;
          917  +  }
          918  +  available = SQLITE_PAGE_SIZE/sizeof(u32) - j;
          919  +
          920  +  /* If the new entry will not fit, try to move some of the entries
          921  +  ** from this leaf onto sibling leaves.
          922  +  */
          923  +  if( available<minNeeded ){
          924  +    int newSpace;
          925  +    newSpace = sqliteDbSpreadLoad(pCur, maxNeeded); ############
          926  +    available += newSpace;
          927  +  }
          928  +
          929  +  /* If the new entry still will not fit, try to split this leaf into
          930  +  ** two adjacent leaves.
          931  +  */
          932  +  if( available<minNeeded && pCur->nLevel>1 ){
          933  +    int newAvail;
          934  +    newAvail = sqliteDbSplit(pCur, maxNeeded); ##############
          935  +    if( newAvail>0 ){
          936  +      available += newAvail;
          937  +    }
          938  +  }
          939  +
          940  +  /* If the new entry does not fit after splitting, turn this leaf into
          941  +  ** and index node with one leaf, go down into the new leaf and try 
          942  +  ** to split again.
          943  +  */
          944  +  if( available<minNeeded && pCur->nLevel<MAX_LEVEL-1 ){
          945  +    int newAvail;
          946  +    sqliteDbNewIndexLevel(pCur);  ###############
          947  +    newAvail = sqliteDbSplit(pCur, maxNeeded);
          948  +    if( newAvail>0 ){
          949  +      available = newAvail;
          950  +    }
          951  +  }
          952  +
          953  +  /* If the entry still will not fit, it means the database is full.
          954  +  */
          955  +  if( available<minNeeded ){
          956  +    return SQLITE_FULL;
          957  +  }
          958  +
          959  +  /* Add the new entry to the leaf block.
          960  +  */
          961  +  aPage = pCur->aLevel[pCur->nLevel-1].aPage;
          962  +  i = 2;
          963  +  for(;;){
          964  +    int entrySize = SWB(aPage[i]);
          965  +    if( entrySize<=0 || entrySize + i >= SQLITE_PAGE_SIZE/sizeof(u32) ) break;
          966  +    i += entrySize;
          967  +  }
          968  +  assert( available==SQLITE_PAGE_SIZE/sizeof(u32) - i );
          969  +  aPage[i+1] = SWB(h);
          970  +  available -= 5;
          971  +  if( nKeyU <= available ){
          972  +    aPage[i+2] = SWB(nKey);
          973  +    memcpy(&aPage[i+4], pKey, nKey);
          974  +    j = i + 4 + nKeyU;
          975  +    available -= nKeyU;
          976  +  }else{
          977  +    u32 newPgno, *newPage;
          978  +    aPage[i+2] = SWB(nKey | 0x80000000);
          979  +    rc = sqliteDbAllocPage(pCur->pDb, &newPgno, &newPage);
          980  +    if( rc!=SQLITE_OK ) goto write_err;
          981  +    aPage[i+4] = SWB(newPgno);
          982  +    rc = sqliteDbWriteOvfl(pCur->pDb, newPgno, newPage, nKey, pKey); ########
          983  +    if( rc!=SQLITE_OK ) goto write_err;
          984  +    j = i + 5;
          985  +    available -= 1;
          986  +  }
          987  +  if( nDataU <= available ){
          988  +    aPage[i+3] = SWB(nData);
          989  +    memcpy(&aPage[j], pData, nData);
          990  +    available -= nDataU;
          991  +    j += nDataU;
          992  +  }else{
          993  +    u32 newPgno, *newPage;
          994  +    aPage[i+3] = SWB(nData | 0x80000000);
          995  +    rc = sqliteDbAllocPage(pCur->pDb, &newPgno, &newPage);
          996  +    if( rc!=SQLITE_OK ) goto write_err;
          997  +    aPage[j] = SWB(newPgno);
          998  +    rc = sqliteDbWriteOvfl(pCur->pDb, newPgno, newPage, nData, pData);
          999  +    if( rc!=SQLITE_OK ) goto write_err;
         1000  +    available -= 1;
         1001  +    j++;
         1002  +  }    
         1003  +  if( j<SQLITE_PAGE_SIZE/sizeof(u32) ){
         1004  +    aPage[j] = 0;
         1005  +  }
         1006  +  sqlitePgTouch(aPage);
         1007  +  pCur->aLevel[pCur->nLevel-1].idx = i;
         1008  +  pCur->onEntry = 1;
         1009  +
         1010  +  /*  Increment the entry count for this table.
         1011  +  */
         1012  +  if( incr!=0 ){
         1013  +    pCur->aLevel[0].aPage[1] = SWB(SWB(pCur->aLevel[0].aPage[1])+incr);
         1014  +    sqlitePgTouch(pCur->aLevel[0].aPage);
         1015  +  }
         1016  +  return SQLITE_OK;
         1017  +
         1018  +write_err:
         1019  +  aPage[i] = 0;
         1020  +  pCur->onEntry = 0;
         1021  +  return rc;
         1022  +}
         1023  +
         1024  +/*
         1025  +** The cursor is pointing to a particular entry of an index page
         1026  +** when this routine is called.  This routine frees everything that
         1027  +** is on the page that the index entry points to.
         1028  +*/
         1029  +static int sqliteDbPruneTree(DbCursor *pCur){
         1030  +  int i, idx;
         1031  +  u32 *aPage;
         1032  +  int from, to, limit, n;
         1033  +  int rc;
         1034  +
         1035  +  i = pCur->nLevel-1;
         1036  +  assert( i>=0 && i<MAX_LEVEL );
         1037  +  idx = pCur->aLevel[i].idx;
         1038  +  aPage = pCur->aLevel[i].aPage;
         1039  +  assert( SWB(aPage[0])==BLOCK_MAGIC|BLOCK_INDEX );
         1040  +  assert( idx>=3 && idx<SQLITE_PAGE_SIZE/sizeof(u32) );
         1041  +  n = SWB(aPage[2]);
         1042  +  assert( n>=2 && n<=SQLITE_PAGE_SIZE/2*sizeof(u32)-2 );
         1043  +  sqliteDbDropPage(pCur->pDb, SWB(aPage[idx+1]);
         1044  +  to = idx;
         1045  +  from = idx+2;
         1046  +  limit = n*2 + 3;
         1047  +  while( from<limit ){
         1048  +    aPage[to++] = aPage[from++];
         1049  +  }
         1050  +  n--;
         1051  +  if( n==1 ){
         1052  +    u32 oldPgno, *oldPage;
         1053  +    oldPgno = SWB(aPage[4]);
         1054  +    rc = sqlitePgGet(pCur->pDb->pPgr, oldPgno, &oldPage);
         1055  +    if( rc!=SQLITE_OK ){
         1056  +      return rc;  /* Do something smarter here */
         1057  +    }
         1058  +    memcpy(aPage, oldPage, SQLITE_PAGE_SIZE);
         1059  +    oldPage[0] = SWB(BLOCK_MAGIC|BLOCK_OVERFLOW);
         1060  +    oldPage[1] = 0;
         1061  +    sqliteDbDropPage(pCur->pDb, oldPgno);
         1062  +    sqlitePgUnref(oldPage);
         1063  +  }else{
         1064  +    aPage[2] = SWB(n);
         1065  +  }
         1066  +  sqlitePgTouch(aPage);
         1067  +  return SQLITE_OK;
         1068  +}
         1069  +
         1070  +/*
         1071  +** Delete the entry that the cursor points to.
         1072  +*/
         1073  +int sqliteDbCursorDelete(DbCursor *pCur){
         1074  +  int i, idx;
         1075  +  int from, to;
         1076  +  int entrySize;
         1077  +  u32 *aPage;
         1078  +  if( !pCur->onEntry ) return SQLITE_NOTFOUND;
         1079  +
         1080  +  /* Delete the entry that the cursor is pointing to.
         1081  +  */
         1082  +  i = pCur->nLevel - 1;
         1083  +  aPage = pCur->aLevel[i].aPage;
         1084  +  idx = pCur->aLevel[i].idx;
         1085  +  assert( SWB(aPage[0])==BLOCK_MAGIC|BLOCK_LEAF );
         1086  +  assert( idx>=2 && idx<SQLITE_PAGE_SIZE/sizeof(u32)-4 );
         1087  +  entrySize = SWB(aPage[idx]);
         1088  +  assert( entrySize>=6 && idx+entrySize<=SQLITE_PAGE_SIZE/sizeof(u32) );
         1089  +  sqliteDbClearEntry(pCur->pDb, &aPage[idx]);
         1090  +  to = idx;
         1091  +  from = idx + entrySize;
         1092  +  while( from<SQLITE_PAGE_SIZE/sizeof(u32) ){
         1093  +    int k;
         1094  +    entrySize = SWB(aPage[from]);
         1095  +    if( entrySize<=0 ) break;
         1096  +    for(k=0; k<entrySize; k++){
         1097  +      aPage[to++] = aPage[from++]
         1098  +    }
         1099  +  }
         1100  +  aPage[to] = 0;
         1101  +
         1102  +  /*  Decrement the entry count for this table.
         1103  +  */
         1104  +  pCur->aLevel[0].aPage[1] = SWB(SWB(pCur->aLevel[0].aPage[1])-1);
         1105  +  sqlitePgTouch(pCur->aLevel[0].aPage);
         1106  +
         1107  +  /* If there are more entries on this leaf or this leaf is the root
         1108  +  ** of the table,  then we are done.
         1109  +  */
         1110  +  if( to>2 || pCur->nLevel==1 ) return SQLITE_OK;
         1111  +
         1112  +  /* Collapse the tree into a more compact form.
         1113  +  */
         1114  +  sqliteDbResetCursor(pCur, pCur->nLevel-1);
         1115  +
         1116  +  return sqliteDbPruneTree(pCur);
         1117  +}

Changes to src/db.h.

    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: db.h,v 1.1 2001/01/15 22:51:10 drh Exp $
           24  +** $Id: db.h,v 1.2 2001/01/20 19:52:49 drh Exp $
    25     25   */
    26     26   
    27     27   typedef struct Db Db;
    28     28   typedef struct DbCursor DbCursor;
    29     29   
    30     30   int sqliteDbOpen(const char *filename, Db**);
    31     31   int sqliteDbClose(Db*);
    32     32   int sqliteDbBeginTransaction(Db*);
    33     33   int sqliteDbCommit(Db*);
    34     34   int sqliteDbRollback(Db*);
    35     35   
    36         -int sqliteDbCreateTable(Db*, int *pPgno);
    37         -int sqliteDbDropTable(Db*, int pgno);
           36  +int sqliteDbCreateTable(Db*, int *pTblno);
           37  +int sqliteDbDropTable(Db*, int tblno);
    38     38   
    39         -int sqliteDbCursorOpen(Db*, int pgno, DbCursor**);
           39  +int sqliteDbCursorOpen(Db*, int tblno, DbCursor**);
    40     40   int sqliteDbCursorClose(DbCursor*);
    41     41   
    42         -int sqliteDbCursorMoveTo(DbCursor*, int key);
    43     42   int sqliteDbCursorFirst(DbCursor*);
    44     43   int sqliteDbCursorNext(DbCursor*);
    45         -int sqliteDbCursorDelete(DbCursor*);
    46     44   int sqliteDbCursorDatasize(DbCursor*);
           45  +int sqliteDbCursorKeysize(DbCursor*);
    47     46   int sqliteDbCursorRead(DbCursor*, int amt, int offset, char *buf);
    48         -int sqliteDbCursorInsert(DbCursor*, int key, int nData, char *pData);
           47  +int sqliteDbCursorReadKey(DbCursor*, int amt, int offset, char *buf);
           48  +int sqliteDbCursorMoveTo(DbCursor*, int nKey, void *pKey);
           49  +int sqliteDbCursorDelete(DbCursor*);
           50  +int sqliteDbCursorInsert(DbCursor*, int nKey, void *pKey, int nData, void *pD);
    49     51   
    50         -int sqliteDbCursorMoveToIdx(DbCursor*, int nKey, char *pKey);
    51         -int sqliteDbCursorKeysize(DbCursor*);
    52         -int sqliteDbCursorReadKey(DbCursor*, int amt, int offset, char *buf);
    53         -int sqliteDbCursorInsertIdx(DbCursor*, int nKey, char *pKey, int nData, char*);
           52  +int sqliteDbReorganize(Db*);

Changes to src/pg.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: pg.c,v 1.1 2001/01/15 22:51:11 drh Exp $
           24  +** $Id: pg.c,v 1.2 2001/01/20 19:52:49 drh Exp $
    25     25   */
    26     26   #include <assert.h>
    27     27   #include <sys/types.h>
    28     28   #include <sys/stat.h>
    29     29   #include <fcntl.h>
    30     30   #include <unistd.h>
    31     31   #include "sqliteInt.h"
................................................................................
   691    691     return SQLITE_OK;
   692    692   }
   693    693   
   694    694   /*
   695    695   ** Return the number of the first unused page at the end of the
   696    696   ** database file.
   697    697   */
   698         -int sqlitePgAlloc(Pgr *p, int *pPgno){
          698  +int sqlitePgAlloc(Pgr *p, u32 *pPgno){
   699    699     *pPgno = p->nDbPg;
   700    700     return SQLITE_OK;
   701    701   }
          702  +
          703  +/*
          704  +** Return the page number associated with the given page.
          705  +*/
          706  +u32 sqlitePgNum(void *pD){
          707  +  Pghdr *pPg = DATA_TO_PG(pD);
          708  +  return pPg->dbpgno;
          709  +}

Changes to src/pg.h.

    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: pg.h,v 1.1 2001/01/15 22:51:11 drh Exp $
           24  +** $Id: pg.h,v 1.2 2001/01/20 19:52:49 drh Exp $
    25     25   */
    26     26   
    27     27   typedef struct Pgr Pgr;
    28     28   #define SQLITE_PAGE_SIZE 1024
    29     29   
    30         -/*
    31         -** The paging system deals with 32-bit integers.
    32         -*/
    33         -typedef unsigned int u32;
    34     30   
    35     31   int sqlitePgOpen(const char *filename, Pgr **pp);
    36     32   int sqlitePgClose(Pgr*);
    37     33   int sqlitePgBeginTransaction(Pgr*);
    38     34   int sqlitePgCommit(Pgr*);
    39     35   int sqlitePgRollback(Pgr*);
    40     36   int sqlitePgGet(Pgr*, u32 pgno, void **);
    41     37   int sqlitePgUnref(void*);
    42     38   int sqlitePgTouch(void*);
    43         -int sqlitePgAlloc(Pgr*, int*);
           39  +int sqlitePgAlloc(Pgr*, u32*);
           40  +u32 sqlitePgNum(void*);

Changes to src/sqlite.h.in.

    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 library
    25     25   ** presents to client programs.
    26     26   **
    27         -** @(#) $Id: sqlite.h.in,v 1.8 2001/01/15 22:51:11 drh Exp $
           27  +** @(#) $Id: sqlite.h.in,v 1.9 2001/01/20 19:52:49 drh Exp $
    28     28   */
    29     29   #ifndef _SQLITE_H_
    30     30   #define _SQLITE_H_
    31     31   #include <stdarg.h>     /* Needed for the definition of va_list */
    32     32   
    33     33   /*
    34     34   ** The version of the SQLite library.
................................................................................
   135    135   #define SQLITE_PERM      3    /* Access permission denied */
   136    136   #define SQLITE_ABORT     4    /* Callback routine requested an abort */
   137    137   #define SQLITE_BUSY      5    /* One or more database files are locked */
   138    138   #define SQLITE_NOMEM     6    /* A malloc() failed */
   139    139   #define SQLITE_READONLY  7    /* Attempt to write a readonly database */
   140    140   #define SQLITE_INTERRUPT 8    /* Operation terminated by sqlite_interrupt() */
   141    141   #define SQLITE_IOERR     9    /* Disk full or other I/O error */
          142  +#define SQLITE_CORRUPT   10   /* The database disk image is malformed */
          143  +#define SQLITE_NOTFOUND  11   /* Table or record not found */
          144  +#define SQLITE_FULL      12   /* Insertion failed because database is full */
   142    145   
   143    146   /* This function causes any pending database operation to abort and
   144    147   ** return at its earliest opportunity.  This routine is typically
   145    148   ** called in response to a user action such as pressing "Cancel"
   146    149   ** or Ctrl-C where the user wants a long query operation to halt
   147    150   ** immediately.
   148    151   */

Changes to src/sqliteInt.h.

    19     19   ** Author contact information:
    20     20   **   drh@hwaci.com
    21     21   **   http://www.hwaci.com/drh/
    22     22   **
    23     23   *************************************************************************
    24     24   ** Internal interface definitions for SQLite.
    25     25   **
    26         -** @(#) $Id: sqliteInt.h,v 1.35 2001/01/15 22:51:11 drh Exp $
           26  +** @(#) $Id: sqliteInt.h,v 1.36 2001/01/20 19:52:50 drh Exp $
    27     27   */
    28     28   #include "sqlite.h"
    29     29   #include "dbbe.h"
    30     30   #include "vdbe.h"
    31     31   #include "parse.h"
    32     32   #include <gdbm.h>
    33     33   #include <stdio.h>
    34     34   #include <stdlib.h>
    35     35   #include <string.h>
    36     36   #include <assert.h>
    37     37   
           38  +/*
           39  +** The paging system deals with 32-bit integers.
           40  +*/
           41  +typedef unsigned int u32;
           42  +
    38     43   /*
    39     44   ** If memory allocation problems are found, recompile with
    40     45   **
    41     46   **      -DMEMORY_DEBUG=1
    42     47   **
    43     48   ** to enable some sanity checking on malloc() and free().  To
    44     49   ** check for memory leaks, recompile with