/ Check-in [7da856cd]
Login

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

Overview
Comment:Bug fixes and speed improvements. Delete is still slow. (CVS 244)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:7da856cd94d2572070e40762e5bc477679e60042
User & Date: drh 2001-09-14 16:42:12
Context
2001-09-14
18:54
Added a PRAGMA statement. Took out the special comment parsing. (CVS 245) check-in: 5e372460 user: drh tags: trunk
16:42
Bug fixes and speed improvements. Delete is still slow. (CVS 244) check-in: 7da856cd user: drh tags: trunk
03:24
All tests now pass. But there are still issues. For example, inserts are way too slow. And additional tests are needed for new features. (CVS 243) check-in: e7b65e37 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

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.25 2001/09/14 03:24:24 drh Exp $
           24  +** $Id: btree.c,v 1.26 2001/09/14 16:42:12 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.
................................................................................
  1698   1698     MemPage aOld[3];             /* Temporary copies of pPage and its siblings */
  1699   1699   
  1700   1700     /* 
  1701   1701     ** Return without doing any work if pPage is neither overfull nor
  1702   1702     ** underfull.
  1703   1703     */
  1704   1704     assert( sqlitepager_iswriteable(pPage) );
  1705         -  if( !pPage->isOverfull && pPage->nFree<SQLITE_PAGE_SIZE/2 && pPage->nCell>=2){
         1705  +  if( !pPage->isOverfull && pPage->nFree<SQLITE_PAGE_SIZE/2 
         1706  +        && pPage->nCell>=2){
  1706   1707       relinkCellList(pPage);
  1707   1708       return SQLITE_OK;
  1708   1709     }
  1709   1710   
  1710   1711     /*
  1711   1712     ** Find the parent of the page to be balanceed.
  1712   1713     ** If there is no parent, it means this page is the root page and

Changes to src/main.c.

    22     22   **
    23     23   *************************************************************************
    24     24   ** Main file for the SQLite library.  The routines in this file
    25     25   ** implement the programmer interface to the library.  Routines in
    26     26   ** other files are for internal use by SQLite and should not be
    27     27   ** accessed by users of the library.
    28     28   **
    29         -** $Id: main.c,v 1.34 2001/09/13 21:53:10 drh Exp $
           29  +** $Id: main.c,v 1.35 2001/09/14 16:42:12 drh Exp $
    30     30   */
    31     31   #include "sqliteInt.h"
    32     32   #if defined(HAVE_USLEEP) && HAVE_USLEEP
    33     33   #include <unistd.h>
    34     34   #endif
    35     35   
    36     36   /*
................................................................................
   239    239   
   240    240     /* Allocate the sqlite data structure */
   241    241     db = sqliteMalloc( sizeof(sqlite) );
   242    242     if( pzErrMsg ) *pzErrMsg = 0;
   243    243     if( db==0 ) goto no_mem_on_open;
   244    244     
   245    245     /* Open the backend database driver */
   246         -  rc = sqliteBtreeOpen(zFilename, mode, 100, &db->pBe);
          246  +  rc = sqliteBtreeOpen(zFilename, mode, MAX_PAGES, &db->pBe);
   247    247     if( rc!=SQLITE_OK ){
   248    248       switch( rc ){
   249    249         default: {
   250    250           if( pzErrMsg ){
   251    251             sqliteSetString(pzErrMsg, "unable to open database: ", zFilename, 0);
   252    252           }
   253    253         }

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 to one writer.
    29     29   **
    30         -** @(#) $Id: pager.c,v 1.16 2001/09/14 03:24:25 drh Exp $
           30  +** @(#) $Id: pager.c,v 1.17 2001/09/14 16:42:12 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>
................................................................................
    99     99   #define DATA_TO_PGHDR(D)  (&((PgHdr*)(D))[-1])
   100    100   #define PGHDR_TO_EXTRA(P) ((void*)&((char*)(&(P)[1]))[SQLITE_PAGE_SIZE])
   101    101   
   102    102   /*
   103    103   ** How big to make the hash table used for locating in-memory pages
   104    104   ** by page number.  Knuth says this should be a prime number.
   105    105   */
   106         -#define N_PG_HASH 101
          106  +#define N_PG_HASH 907
   107    107   
   108    108   /*
   109    109   ** A open page cache is an instance of the following structure.
   110    110   */
   111    111   struct Pager {
   112    112     char *zFilename;            /* Name of the database file */
   113    113     char *zJournal;             /* Name of the journal file */
................................................................................
  1057   1057   ** Commit all changes to the database and release the write lock.
  1058   1058   **
  1059   1059   ** If the commit fails for any reason, a rollback attempt is made
  1060   1060   ** and an error code is returned.  If the commit worked, SQLITE_OK
  1061   1061   ** is returned.
  1062   1062   */
  1063   1063   int sqlitepager_commit(Pager *pPager){
  1064         -  int i, rc;
         1064  +  int rc;
  1065   1065     PgHdr *pPg;
  1066   1066   
  1067   1067     if( pPager->errMask==PAGER_ERR_FULL ){
  1068   1068       rc = sqlitepager_rollback(pPager);
  1069   1069       if( rc==SQLITE_OK ) rc = SQLITE_FULL;
  1070   1070       return rc;
  1071   1071     }
................................................................................
  1076   1076     if( pPager->state!=SQLITE_WRITELOCK ){
  1077   1077       return SQLITE_ERROR;
  1078   1078     }
  1079   1079     assert( pPager->jfd>=0 );
  1080   1080     if( fsync(pPager->jfd) ){
  1081   1081       goto commit_abort;
  1082   1082     }
  1083         -  for(i=0; i<N_PG_HASH; i++){
  1084         -    for(pPg=pPager->aHash[i]; pPg; pPg=pPg->pNextHash){
  1085         -      if( pPg->dirty==0 ) continue;
  1086         -      rc = pager_seek(pPager->fd, (pPg->pgno-1)*SQLITE_PAGE_SIZE);
  1087         -      if( rc!=SQLITE_OK ) goto commit_abort;
  1088         -      rc = pager_write(pPager->fd, PGHDR_TO_DATA(pPg), SQLITE_PAGE_SIZE);
  1089         -      if( rc!=SQLITE_OK ) goto commit_abort;
  1090         -    }
         1083  +  for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
         1084  +    if( pPg->dirty==0 ) continue;
         1085  +    rc = pager_seek(pPager->fd, (pPg->pgno-1)*SQLITE_PAGE_SIZE);
         1086  +    if( rc!=SQLITE_OK ) goto commit_abort;
         1087  +    rc = pager_write(pPager->fd, PGHDR_TO_DATA(pPg), SQLITE_PAGE_SIZE);
         1088  +    if( rc!=SQLITE_OK ) goto commit_abort;
  1091   1089     }
  1092   1090     if( fsync(pPager->fd) ) goto commit_abort;
  1093   1091     rc = pager_unwritelock(pPager);
  1094   1092     pPager->dbSize = -1;
  1095   1093     return rc;
  1096   1094   
  1097   1095     /* Jump here if anything goes wrong during the commit process.

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.45 2001/09/13 16:18:54 drh Exp $
           26  +** @(#) $Id: sqliteInt.h,v 1.46 2001/09/14 16:42:12 drh Exp $
    27     27   */
    28     28   #include "sqlite.h"
    29     29   #include "vdbe.h"
    30     30   #include "parse.h"
    31     31   #include "btree.h"
    32     32   #include <stdio.h>
    33     33   #include <stdlib.h>
    34     34   #include <string.h>
    35     35   #include <assert.h>
    36     36   
           37  +/*
           38  +** The maximum number of in-memory pages to use for the main database
           39  +** table and for temporary tables.
           40  +*/
           41  +#define MAX_PAGES   150
           42  +#define TEMP_PAGES   50
           43  +
    37     44   /*
    38     45   ** The paging system deals with 32-bit integers.
    39     46   */
    40     47   typedef unsigned int u32;
    41     48   
    42     49   /*
    43     50   ** If memory allocation problems are found, recompile with

Changes to src/vdbe.c.

    37     37   ** inplicit conversion from one type to the other occurs as necessary.
    38     38   ** 
    39     39   ** Most of the code in this file is taken up by the sqliteVdbeExec()
    40     40   ** function which does the work of interpreting a VDBE program.
    41     41   ** But other routines are also provided to help in building up
    42     42   ** a program instruction by instruction.
    43     43   **
    44         -** $Id: vdbe.c,v 1.65 2001/09/14 03:24:25 drh Exp $
           44  +** $Id: vdbe.c,v 1.66 2001/09/14 16:42:12 drh Exp $
    45     45   */
    46     46   #include "sqliteInt.h"
    47     47   #include <ctype.h>
    48     48   #include <unistd.h>
    49     49   
    50     50   /*
    51     51   ** SQL is translated into a sequence of instructions to be
................................................................................
  2005   2005       }
  2006   2006     }
  2007   2007     VERIFY( if( i<0 ) goto bad_instruction; )
  2008   2008     if( i>=p->nCursor ){
  2009   2009       int j;
  2010   2010       p->aCsr = sqliteRealloc( p->aCsr, (i+1)*sizeof(Cursor) );
  2011   2011       if( p->aCsr==0 ){ p->nCursor = 0; goto no_mem; }
  2012         -    for(j=p->nCursor; j<=i; j++) p->aCsr[j].pCursor = 0;
         2012  +    for(j=p->nCursor; j<=i; j++){
         2013  +      memset(&p->aCsr[j], 0, sizeof(Cursor));
         2014  +    }
  2013   2015       p->nCursor = i+1;
  2014   2016     }else if( p->aCsr[i].pCursor ){
  2015   2017       sqliteBtreeCloseCursor(p->aCsr[i].pCursor);
  2016   2018     }
  2017   2019     memset(&p->aCsr[i], 0, sizeof(Cursor));
  2018   2020     do{
  2019   2021       rc = sqliteBtreeCursor(pBt, p2, &p->aCsr[i].pCursor);
................................................................................
  2048   2050     int i = pOp->p1;
  2049   2051     Cursor *pCx;
  2050   2052     VERIFY( if( i<0 ) goto bad_instruction; )
  2051   2053     if( i>=p->nCursor ){
  2052   2054       int j;
  2053   2055       p->aCsr = sqliteRealloc( p->aCsr, (i+1)*sizeof(Cursor) );
  2054   2056       if( p->aCsr==0 ){ p->nCursor = 0; goto no_mem; }
  2055         -    for(j=p->nCursor; j<=i; j++) p->aCsr[j].pCursor = 0;
         2057  +    for(j=p->nCursor; j<=i; j++){
         2058  +      memset(&p->aCsr[j], 0, sizeof(Cursor));
         2059  +    }
  2056   2060       p->nCursor = i+1;
  2057   2061     }else if( p->aCsr[i].pCursor ){
  2058   2062       sqliteBtreeCloseCursor(p->aCsr[i].pCursor);
  2059   2063     }
  2060   2064     pCx = &p->aCsr[i];
  2061   2065     memset(pCx, 0, sizeof(*pCx));
  2062         -  rc = sqliteBtreeOpen(0, 0, 100, &pCx->pBt);
         2066  +  rc = sqliteBtreeOpen(0, 0, TEMP_PAGES, &pCx->pBt);
  2063   2067     if( rc==SQLITE_OK ){
  2064   2068       rc = sqliteBtreeCursor(pCx->pBt, 2, &pCx->pCursor);
  2065   2069     }
  2066   2070     if( rc==SQLITE_OK ){
  2067   2071       rc = sqliteBtreeBeginTrans(pCx->pBt);
  2068   2072     }
  2069   2073     break;
................................................................................
  2200   2204   ** Get a new integer record number used as the key to a table.
  2201   2205   ** The record number is not previous used by the database file
  2202   2206   ** associated with cursor P1.  The new record number pushed 
  2203   2207   ** onto the stack.
  2204   2208   */
  2205   2209   case OP_NewRecno: {
  2206   2210     int i = pOp->p1;
  2207         -  static int v = 0;
         2211  +  int v = 0;
  2208   2212     if( VERIFY( i<0 || i>=p->nCursor || ) p->aCsr[i].pCursor==0 ){
  2209   2213       v = 0;
  2210   2214     }else{
  2211   2215       int res, rx, cnt;
         2216  +    static int x = 0;
         2217  +    union {
         2218  +       char zBuf[sizeof(int)];
         2219  +       int i;
         2220  +    } ux;
  2212   2221       cnt = 0;
  2213   2222       do{
  2214         -      if( v==0 || cnt>5 ){
  2215         -        v = sqliteRandomInteger();
         2223  +      if( x==0 || cnt>5 ){
         2224  +        x = sqliteRandomInteger();
  2216   2225         }else{
  2217         -        v += sqliteRandomByte() + 1;
         2226  +        x += sqliteRandomByte() + 1;
  2218   2227         }
         2228  +      if( x==0 ) continue;
         2229  +      ux.zBuf[3] = x&0xff;
         2230  +      ux.zBuf[2] = (x>>8)&0xff;
         2231  +      ux.zBuf[1] = (x>>16)&0xff;
         2232  +      ux.zBuf[0] = (x>>24)&0xff;
         2233  +      v = ux.i;
  2219   2234         rx = sqliteBtreeMoveto(p->aCsr[i].pCursor, &v, sizeof(v), &res);
  2220   2235         cnt++;
  2221   2236       }while( cnt<10 && rx==SQLITE_OK && res==0 );
  2222   2237     }
  2223   2238     VERIFY( NeedStack(p, p->tos+1); )
  2224   2239     p->tos++;
  2225   2240     aStack[p->tos].i = v;

Changes to test/all.test.

    18     18   # Author contact information:
    19     19   #   drh@hwaci.com
    20     20   #   http://www.hwaci.com/drh/
    21     21   #
    22     22   #***********************************************************************
    23     23   # This file runs all tests.
    24     24   #
    25         -# $Id: all.test,v 1.8 2001/09/13 21:53:10 drh Exp $
           25  +# $Id: all.test,v 1.9 2001/09/14 16:42:13 drh Exp $
    26     26   
    27     27   set testdir [file dirname $argv0]
    28     28   source $testdir/tester.tcl
    29     29   rename finish_test really_finish_test
    30     30   proc finish_test {} {memleak_check}
    31     31   
    32     32   if {[file exists ./sqlite_test_count]} {
................................................................................
    38     38   # LeakList will hold a list of the number of unfreed mallocs after
    39     39   # each round of the test.  This number should be constant.  If it
    40     40   # grows, it may mean there is a memory leak in the library.
    41     41   #
    42     42   set LeakList {}
    43     43   
    44     44   
    45         -for {set Counter 0} {$Counter<$COUNT} {incr Counter} {
           45  +for {set Counter 0} {$Counter<$COUNT && $nErr==0} {incr Counter} {
    46     46     foreach testfile [lsort -dictionary [glob $testdir/*.test]] {
    47     47       if {[file tail $testfile]=="all.test"} continue
    48     48       if {[file tail $testfile]=="malloc.test"} continue
    49     49       source $testfile
    50     50     }
    51     51     if {[info exists Leak]} {
    52     52       lappend LeakList $Leak
................................................................................
    61     61     incr ::nTest
    62     62     foreach x $LeakList {
    63     63       if {$x!=[lindex $LeakList 0]} {
    64     64          puts " failed!"
    65     65          puts "Expected: all values to be the same"
    66     66          puts "     Got: $LeakList"
    67     67          incr ::nErr
           68  +       lappend ::failList memory-leak-test
    68     69          break
    69     70       }
    70     71     }
    71     72     puts " Ok"
    72     73   }
    73     74   
    74     75   if {[file readable $testdir/malloc.test]} {
    75     76     source $testdir/malloc.test
    76     77   }
    77     78   
    78     79   really_finish_test

Changes to test/btree2.test.

    19     19   #   drh@hwaci.com
    20     20   #   http://www.hwaci.com/drh/
    21     21   #
    22     22   #***********************************************************************
    23     23   # This file implements regression tests for SQLite library.  The
    24     24   # focus of this script is btree database backend
    25     25   #
    26         -# $Id: btree2.test,v 1.5 2001/09/13 14:46:11 drh Exp $
           26  +# $Id: btree2.test,v 1.6 2001/09/14 16:42:13 drh Exp $
    27     27   
    28     28   
    29     29   set testdir [file dirname $argv0]
    30     30   source $testdir/tester.tcl
    31     31   
    32     32   if {[info commands btree_open]!=""} {
    33     33   
................................................................................
   284    284   # Repeat this test sequence on database of various sizes
   285    285   #
   286    286   set testno 2
   287    287   foreach {N L} {
   288    288     10 2
   289    289     50 2
   290    290     200 3
   291         -  2000 5
   292    291   } {
          292  +  # 2000 5
   293    293     puts "**** N=$N L=$L ****"
   294    294     set hash [md5file test2.bt]
   295    295     do_test btree2-$testno.1 [subst -nocommands {
   296    296       set ::c2 [btree_cursor $::b 2]
   297    297       set ::c3 [btree_cursor $::b 3]
   298    298       set ::c4 [btree_cursor $::b 4]
   299    299       set ::c5 [btree_cursor $::b 5]

Changes to test/tester.tcl.

    19     19   #   drh@hwaci.com
    20     20   #   http://www.hwaci.com/drh/
    21     21   #
    22     22   #***********************************************************************
    23     23   # This file implements some common TCL routines used for regression
    24     24   # testing the SQLite library
    25     25   #
    26         -# $Id: tester.tcl,v 1.16 2001/09/13 21:53:10 drh Exp $
           26  +# $Id: tester.tcl,v 1.17 2001/09/14 16:42:13 drh Exp $
    27     27   
    28     28   # Make sure tclsqlite was compiled correctly.  Abort now with an
    29     29   # error message if not.
    30     30   #
    31     31   if {[sqlite -tcl-uses-utf]} {
    32     32     if {"\u1234"=="u1234"} {
    33     33       puts stderr "***** BUILD PROBLEM *****"
................................................................................
    64     64   
    65     65   # Set the test counters to zero
    66     66   #
    67     67   set nErr 0
    68     68   set nTest 0
    69     69   set nProb 0
    70     70   set skip_test 0
           71  +set failList {}
    71     72   
    72     73   # Invoke the do_test procedure to run a single test 
    73     74   #
    74     75   proc do_test {name cmd expected} {
    75     76     global argv nErr nTest skip_test
    76     77     if {$skip_test} {
    77     78       set skip_test 0
................................................................................
    91     92     if {!$go} return
    92     93     incr nTest
    93     94     puts -nonewline $name...
    94     95     flush stdout
    95     96     if {[catch {uplevel #0 "$cmd;\n"} result]} {
    96     97       puts "\nError: $result"
    97     98       incr nErr
    98         -    if {$nErr>10} {puts "*** Giving up..."; exit 1}
           99  +    lappend ::failList $name
          100  +    if {$nErr>10} {puts "*** Giving up..."; finalize_testing}
    99    101     } elseif {[string compare $result $expected]} {
   100    102       puts "\nExpected: \[$expected\]\n     Got: \[$result\]"
   101    103       incr nErr
   102         -    if {$nErr>10} {puts "*** Giving up..."; exit 1}
          104  +    lappend ::failList $name
          105  +    if {$nErr>10} {puts "*** Giving up..."; finalize_testing}
   103    106     } else {
   104    107       puts " Ok"
   105    108     }
   106    109   }
   107    110   
   108    111   # Invoke this procedure on a test that is probabilistic
   109    112   # and might fail sometimes.
................................................................................
   156    159       set ::Leak [expr {[lindex $r 0]-[lindex $r 1]}]
   157    160     }
   158    161   }
   159    162   
   160    163   # Run this routine last
   161    164   #
   162    165   proc finish_test {} {
          166  +  finalize_testing
          167  +}
          168  +proc finalize_testing {} {
   163    169     global nTest nErr nProb
   164         -  memleak_check
          170  +  if {$nErr==0} memleak_check
   165    171     catch {db close}
   166    172     puts "$nErr errors out of $nTest tests"
          173  +  puts "Failures on these tests: $::failList"
   167    174     if {$nProb>0} {
   168    175       puts "$nProb probabilistic tests also failed, but this does"
   169    176       puts "not necessarily indicate a malfunction."
   170    177     }
   171    178     exit [expr {$nErr>0}]
   172    179   }
   173    180   

Changes to tool/lempar.c.

   185    185   static char *yyTokenName[] = { 
   186    186   %%
   187    187   };
   188    188   #define YYTRACE(X) if( yyTraceFILE ) fprintf(yyTraceFILE,"%sReduce [%s].\n",yyTracePrompt,X);
   189    189   #else
   190    190   #define YYTRACE(X)
   191    191   #endif
          192  +
   192    193   
   193    194   /*
   194    195   ** This function returns the symbolic name associated with a token
   195    196   ** value.
   196    197   */
   197    198   const char *ParseTokenName(int tokenType){
          199  +#ifndef NDEBUG
   198    200     if( tokenType>0 && tokenType<(sizeof(yyTokenName)/sizeof(yyTokenName[0])) ){
   199    201       return yyTokenName[tokenType];
   200    202     }else{
   201    203       return "Unknown";
   202    204     }
          205  +#else
          206  +  return "";
          207  +#endif
   203    208   }
   204    209   
   205    210   /* 
   206    211   ** This function allocates a new parser.
   207    212   ** The only argument is a pointer to a function which works like
   208    213   ** malloc.
   209    214   **