]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
:-) (CVS 216)
authordrh <drh@noemail.net>
Fri, 11 May 2001 11:02:46 +0000 (11:02 +0000)
committerdrh <drh@noemail.net>
Fri, 11 May 2001 11:02:46 +0000 (11:02 +0000)
FossilOrigin-Name: c3e521190f02120a34f1e9244fe1ea3a975a6caa

manifest
manifest.uuid
notes/notes2.txt
src/btree.c

index b9f7b6165422e6b4f7ccb52a6359e45fc0097583..8a565661183e933425db5ca2301d94f901c1afd5 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C :-)\s(CVS\s215)
-D 2001-04-29T23:32:56
+C :-)\s(CVS\s216)
+D 2001-05-11T11:02:47
 F COPYRIGHT 74a8a6531a42e124df07ab5599aad63870fa0bd4
 F Makefile.in acef0f0275a5ca8e68bda165f7f05d810a207664
 F README 51f6a4e7408b34afa5bc1c0485f61b6a4efb6958
@@ -9,10 +9,10 @@ F configure.in e7465c88bbfb76882f97769c2dd90dbba8eca5db
 F doc/lemon.html e233a3e97a779c7a87e1bc4528c664a58e49dd47
 F doc/report1.txt 734cbae63b1310cc643fe5e9e3da1ab55a79b99e
 F notes/notes1.txt b7c0812b704a022e88c621146ae50955c923d464
-F notes/notes2.txt 80a0c3e3a0063b81fa8df6aab01bd014353dde01
+F notes/notes2.txt 49b4d7ba35f183feb1fb098a27272b82f5c76eca
 F notes/notes3.txt cd5e7bd2167d7ef89b1077abdfa68f0af6337744
 F src/TODO 38a68a489e56e9fd4a96263e0ff9404a47368ad4
-F src/btree.c eb7eec19f54e758c86a231f97fd366cc2d4cffc1
+F src/btree.c 9b985eede929ce3f1a6ad510ecd04c197ce092f7
 F src/btree.h f21c240d0c95f93e2a128106d04a6c448ed0eb94
 F src/build.c 4f6a2d551c56342cd4a0420654835be3ad179651
 F src/dbbe.c b18259f99d87240cbe751021cf14dd3aa83a48af
@@ -106,7 +106,7 @@ F www/opcode.tcl cb3a1abf8b7b9be9f3a228d097d6bf8b742c2b6f
 F www/sqlite.tcl cb0d23d8f061a80543928755ec7775da6e4f362f
 F www/tclsqlite.tcl 06f81c401f79a04f2c5ebfb97e7c176225c0aef2
 F www/vdbe.tcl 0c8aaa529dd216ccbf7daaabd80985e413d5f9ad
-P 73a1ed61265040925f1a41c9c0cfeea50db70b01
-R 6983c25437d4d42e0292396f95237df8
+P 624ccbca98be33a26c2af72d2d91c78f8a06ae9c
+R dd7612c12a95a523d5ea5cc83b2e1f75
 U drh
-Z 352332e9d2b2a7ec788ddf63618fa616
+Z 7bf915d3af7096b69289ffd2ecea3428
index 8fb1accbfd836fb31827ae8fed49a0e7fab239e6..5a727989b23e2ca0cba9327c5349c52b133daa15 100644 (file)
@@ -1 +1 @@
-624ccbca98be33a26c2af72d2d91c78f8a06ae9c
\ No newline at end of file
+c3e521190f02120a34f1e9244fe1ea3a975a6caa
\ No newline at end of file
index 2420530d0f6c37f6db0e1880b28dd509f03516de..5fddce272c791ae9876e2c05f89924c4064bc4ca 100644 (file)
 How to do a B*Tree insert:
 
-add_to_page(cursor, data, ptr){
-  if( data_fits_on_page ){ add data to page; return; }
-  if( page==root ){
-     split currentpage+(data+ptr) into lowerpart, center, upperpart
-     newpage1 = lowerpart;
-     newpage2 = upperpart;
-     page = ptr(newpage1) + center + ptr(newpage2);
-     return;
+add_to_page(pageptr, data, pgno){
+  pgno.parent = pageptr
+  if( data+pgno fits on pageptr ){
+    add data+pgno to pageptr
+    return
+  }
+  if( pageptr==root ){
+    split pageptr+(data+pgno) into newpage1, center, newpage2
+    pageptr = ptr(newpage1) + center + ptr(newpage2);
+    return
   }
   if( move_some_data_left || move_some_data_right ){
-    add data to page
+    add data+pgno to pageptr
     return
   }
-  split currentpage+(data+ptr) into lowerpart, center, upperpart
-  newpage = upperpart
-  currentpage = lowerpart
-  pop cursor one level
-  add_to_page(cursor, center, ptr(newpage));
+  split pageptr+(data+pgno) into pageptr, center, newpage
+  add_to_page(parent(pageptr), center, ptr(newpage));
+  newpage.parent = parent(pageptr)
 }
 
+Cursor: pageptr, idx
+
 unlink_entry(cursor, olddata){
-  if( !is_a_leaf ){
-    n = next_entry()
-    if( n fits pageof(cursor) ){
-      if( olddata!=nil ) copy dataof(cursor) into olddata
-      copy dataof(n) into dataof(cursor)
+  if( cursor.pageptr is not a leaf page ){
+    if( olddata!=nil) copy payload(cursor) into olddata
+    n = next_entry(cursor)
+    if( payloadsize(n) <= freesize(cursor) + payloadsize(cursor) ){
+      copy payload(n) into payload(cursor)
       unlink_entry(n, nil)
       return
     }
-    n = prev_entry()
-    if( n fits pageof(cursor) ){
-      if( olddata!=nil ) copy dataof(cursor) into olddata
-      copy dataof(n) into dataof(cursor)
-      unlink_entry(n, nil)
+    p = prev_entry(cursor)
+    if( payloadsize(p) <= freesize(cursor) + payloadsize(cursor) ){
+      copy payload(p) into payload(cursor)
+      unlink_entry(p, nil)
       return
     }
-    unlink_entry(n, leafdata)
-    move cursor data and ptr into olddata, oldptr
-    add_to_page(cursor, leafdata, oldptr)
+    unlink(n, leafdata)
+    pageptr = cursor.pageptr
+    nextpgno = pageptr.aCell[cursor.idx].pgno;
+    convert_cursor_to_free_block(cursor)
+    add_to_page(pageptr, leafdata, nextpgno)
     return
   }
-  move cursor data into olddata
-  if( !underfull(pageof(cursor)) ) return
+  pageptr = cursor.pageptr;
+  convert_cursor_to_free_block(cursor)
+  if( usage(pageptr)<0.65 ){
+    consolidate(pageptr)
+  }
+}
 
+consolidate(pageptr){
+  parentpage = parentof(pageptr)
+  idx = index_of_page(parentpage, pageptr);
+  leftsibling = parentpage.cell[idx].pgno;
+  rightsibling = parentpage.cell[idx+1].pgno;
+  if( idx>0 ){
+    cursor = makecursor(pageptr,idx-1)
+    if( try_to_move_down(cursor) ) return
+  }
+  if( idx<max ){
+    cursor = makecursor(pageptr,idx)
+    try_to_move_down(cursor)
+  }
+  return
+}
 
+try_to_move_down(cursor){
+  pageptr = cursor.pageptr
+  if( payload(cursor)+sizeof(left)+sizeof(right)<=pagesize ){
+    put cursor and content of left into right
+    remove cursor from pageptr
+    if( pageptr is root ){
+      if( cellcount(pageptr)==0 ){
+        copy child into pageptr
+        update parent field of child
+      }
+    }else if( usage(pageptr)<0.65 ){
+      try_to_move_down(cursor)
+    }
+  }
+}
+
+cursor_move_next(cursor){
+  if( cursor.incr_noop ){
+    cursor.incr_noop = FALSE;
+    return;
+  }
+  if( is_leaf(cursor.pageptr) ){
+    if( cursor.idx==cursor.pageptr.ncell ){
+      if( cursor.pageptr==root ){
+        nil cursor
+        return
+      }
+      cursor_move_up(cursor)
+      cursor_move_next(cursor)
+    }else{
+      cursor.idx++;
+    }
+    return
+  }
+  pgno = next_pgno(cursor)
+  loop {
+    cursor.pageptr = get(pgno);
+    if( is_leaf(cursor.pageptr) ) break;
+    pgno = first_pgno(pageptr);
+  }
+  cursor.idx = 0;
 }
index c310dc3a335d3c0ac5f735d618a433c1c0fdf18b..0048edd52547875adf6b895ae795a61a42451883 100644 (file)
@@ -21,7 +21,7 @@
 **   http://www.hwaci.com/drh/
 **
 *************************************************************************
-** $Id: btree.c,v 1.3 2001/04/29 23:32:56 drh Exp $
+** $Id: btree.c,v 1.4 2001/05/11 11:02:47 drh Exp $
 */
 #include "sqliteInt.h"
 #include "pager.h"
 #include <assert.h>
 
 typedef unsigned int u32;
+typedef unsigned short int u16;
+
+/*
+** Forward declarations of structures used only in this file.
+*/
+typedef struct Page1Header Page1Header;
+typedef struct PageHdr PageHdr;
+typedef struct Cell Cell;
+typedef struct FreeBlk FreeBlk;
 
 
 /*
@@ -42,6 +51,12 @@ typedef unsigned int u32;
 #define MAGIC_1  0x7264dc61
 #define MAGIC_2  0x54e55d9e
 
+struct Page1Header {
+  u32 magic1;
+  u32 magic2;
+  Pgno firstList;
+};
+
 /*
 ** Each database page has a header as follows:
 **
@@ -57,6 +72,22 @@ typedef unsigned int u32;
 **      nByte                 Number of free bytes in this block
 **      next_free             Next free block or 0 if this is the end
 */
+struct PageHdr {
+  Pgno pgno;      /* Child page that comes after all cells on this page */
+  u16 firstCell;  /* Index in MemPage.aPage[] of the first cell */
+  u16 firstFree;  /* Index in MemPage.aPage[] of the first free block */
+};
+struct Cell {
+  Pgno pgno;      /* Child page that comes before this cell */
+  u16 nKey;       /* Number of bytes in the key */
+  u16 iNext;      /* Index in MemPage.aPage[] of next cell in sorted order */
+  u32 nData;      /* Number of bytes of data */
+  char aData[4];  /* Key and data */
+};
+struct FreeBlk {
+  u16 iSize;      /* Number of u32-sized slots in the block of free space */
+  u16 iNext;      /* Index in MemPage.aPage[] of the next free block */
+};
 
 /*
 ** The maximum number of database entries that can be held in a single
@@ -73,7 +104,7 @@ typedef unsigned int u32;
 ** be at least 4 bytes in the key/data packet, so each entry consumes at
 ** least 20 bytes of space on the page.
 */
-#define MX_CELL ((SQLITE_PAGE_SIZE-12)/20)
+#define MX_CELL ((SQLITE_PAGE_SIZE-sizeof(PageHdr))/sizeof(Cell))
 
 /*
 ** The maximum amount of data (in bytes) that can be stored locally for a
@@ -109,7 +140,7 @@ struct MemPage {
   Pgno left;                   /* Left sibling page.  0==none */
   Pgno right;                  /* Right sibling page.  0==none */
   int idxStart;                /* Index in aPage[] of real data */
-  int nFree;                   /* Number of free elements of aPage[] */
+  int nFree;                   /* Number of free slots of aPage[] */
   int nCell;                   /* Number of entries on this page */
   u32 *aCell[MX_CELL];         /* All entires in sorted order */
 }
@@ -133,6 +164,17 @@ struct Btree {
 };
 typedef Btree Bt;
 
+/*
+** A cursor is a pointer to a particular entry in the BTree.
+** The entry is identified by its MemPage and the index in
+** MemPage.aCell[] of the entry.
+*/
+struct Cursor {
+  Btree *pBt;           /* The pointer back to the BTree */
+  MemPage *pPage;       /* Page that contains the entry */
+  int idx;              /* Index of the entry in pPage->aCell[] */
+  int skip_incr;        /* */
+};
 
 /*
 ** The maximum depth of a cursor
@@ -163,83 +205,25 @@ struct BtCursor {
   BtIdxpt aLevel[MX_LEVEL];     /* The index levels */
 };
 
+
 /*
-** Mark a section of the memory block as in-use.
+** Defragment the page given.  All of the free space
+** is collected into one big block at the end of the
+** page.
 */
-static void useSpace(MemPage *pPage, int start, int size){
-  int i;
-  FreeBlk *p;
-
-  /* Some basic sanity checking */
-  assert( pPage && pPage->isInit );
-  assert( pPage->nFree>0 && pPage->nFree<=MX_FREE );
-  assert( pPage->nFreeSlot >= size );
-  assert( start > pPage->idxStart );
-  assert( size>0 );
-  assert( start + size < SQLITE_PAGE_SIZE/sizeof(pPage->aPage[0]) );
-
-  /* Search for the freeblock that describes the space to be used */
-  for(i=0; i<pPage->nFree; i++){
-    p = &pPage->aFree[i]
-    if( p->idx<=start && p->idx+p->size>start ) break;
-  }
-
-  /* The freeblock must contain all the space that is to be used */
-  assert( i<pPage->nFree );
-  assert( p->idx+p->size >= start+size );
-
-  /* Remove the used space from the freeblock */
-  if( p->idx==start ){
-    /* The space is at the beginning of the block
-    p->size -= size;
-    if( p->size==0 ){
-      *p = pPage->aFree[pPage->nFree-1];
-      pPage->nFree--;
-    }
-  }else if( p->idx+p->size==start+size ){
-    /* Space at the end of the block */
-    p->size -= size;
-  }else{
-    /* Space in the middle of the freeblock. */
-    FreeBlk *pNew;
-    assert( p->nFreeSlot < MX_FREE );
-    pNew->idx = start+size;
-    pNew->size = p->idx+p->size - pNew->idx;
-    p->size = start - p->idx;
-  }
-  pPage->nFreeSlot -= size;
+static void defragmentPage(MemPage *pPage){
 }
 
 /*
-** Return a section of the MemPage.aPage[] to the freelist.
+** Mark a section of the memory block as in-use.
 */
-static void freeSpace(MemPage *pPage, int start, int size){
-  int end = start+size;
-  int i;
-  FreeBlk *pMatch = 0;
-  FreeBlk *
-  for(i=0; i<pPage->nFreeSlot; i++){
-    FreeBlk *p = &pPage->aFree[i];
-    if( p->idx==end+1 ){
-      if( pMatch ){
-        
-      }else{
-        p->idx = start;
-        p->size += size;
-        pMatch = p;
-      }
-    }
-    if( p->idx+p->size+1==start ){
-      p->size += size;
-      break;
-    }
-  }
+static void useSpace(MemPage *pPage, int start, int size){
 }
 
 /*
-** Defragment the freespace
+** Return a section of the MemPage.aPage[] to the freelist.
 */
-static void defragmentSpace(MemPage *pPage){
+static void freeSpace(MemPage *pPage, int start, int size){
 }
 
 /*