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 |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
7da856cd94d2572070e40762e5bc4776 |
User & Date: | drh 2001-09-14 16:42:12.000 |
Context
2001-09-14
| ||
18:54 | Added a PRAGMA statement. Took out the special comment parsing. (CVS 245) (check-in: 5e3724603e user: drh tags: trunk) | |
16:42 | Bug fixes and speed improvements. Delete is still slow. (CVS 244) (check-in: 7da856cd94 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: e7b65e37fd user: drh tags: trunk) | |
Changes
Changes to src/btree.c.
︙ | ︙ | |||
17 18 19 20 21 22 23 | ** Boston, MA 02111-1307, USA. ** ** Author contact information: ** drh@hwaci.com ** http://www.hwaci.com/drh/ ** ************************************************************************* | | | 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | ** Boston, MA 02111-1307, USA. ** ** Author contact information: ** drh@hwaci.com ** http://www.hwaci.com/drh/ ** ************************************************************************* ** $Id: btree.c,v 1.26 2001/09/14 16:42:12 drh Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** For a detailed discussion of BTrees, refer to ** ** Donald E. Knuth, THE ART OF COMPUTER PROGRAMMING, Volume 3: ** "Sorting And Searching", pages 473-480. Addison-Wesley ** Publishing Company, Reading, Massachusetts. |
︙ | ︙ | |||
1698 1699 1700 1701 1702 1703 1704 | MemPage aOld[3]; /* Temporary copies of pPage and its siblings */ /* ** Return without doing any work if pPage is neither overfull nor ** underfull. */ assert( sqlitepager_iswriteable(pPage) ); | | > | 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 | MemPage aOld[3]; /* Temporary copies of pPage and its siblings */ /* ** Return without doing any work if pPage is neither overfull nor ** underfull. */ assert( sqlitepager_iswriteable(pPage) ); if( !pPage->isOverfull && pPage->nFree<SQLITE_PAGE_SIZE/2 && pPage->nCell>=2){ relinkCellList(pPage); return SQLITE_OK; } /* ** Find the parent of the page to be balanceed. ** If there is no parent, it means this page is the root page and |
︙ | ︙ |
Changes to src/main.c.
︙ | ︙ | |||
22 23 24 25 26 27 28 | ** ************************************************************************* ** Main file for the SQLite library. The routines in this file ** implement the programmer interface to the library. Routines in ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** | | | 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | ** ************************************************************************* ** Main file for the SQLite library. The routines in this file ** implement the programmer interface to the library. Routines in ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** ** $Id: main.c,v 1.35 2001/09/14 16:42:12 drh Exp $ */ #include "sqliteInt.h" #if defined(HAVE_USLEEP) && HAVE_USLEEP #include <unistd.h> #endif /* |
︙ | ︙ | |||
239 240 241 242 243 244 245 | /* Allocate the sqlite data structure */ db = sqliteMalloc( sizeof(sqlite) ); if( pzErrMsg ) *pzErrMsg = 0; if( db==0 ) goto no_mem_on_open; /* Open the backend database driver */ | | | 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 | /* Allocate the sqlite data structure */ db = sqliteMalloc( sizeof(sqlite) ); if( pzErrMsg ) *pzErrMsg = 0; if( db==0 ) goto no_mem_on_open; /* Open the backend database driver */ rc = sqliteBtreeOpen(zFilename, mode, MAX_PAGES, &db->pBe); if( rc!=SQLITE_OK ){ switch( rc ){ default: { if( pzErrMsg ){ sqliteSetString(pzErrMsg, "unable to open database: ", zFilename, 0); } } |
︙ | ︙ |
Changes to src/pager.c.
︙ | ︙ | |||
23 24 25 26 27 28 29 | ************************************************************************* ** This is the implementation of the page cache subsystem. ** ** The page cache is used to access a database file. The pager journals ** all writes in order to support rollback. Locking is used to limit ** access to one or more reader or to one writer. ** | | | 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | ************************************************************************* ** This is the implementation of the page cache subsystem. ** ** The page cache is used to access a database file. The pager journals ** all writes in order to support rollback. Locking is used to limit ** access to one or more reader or to one writer. ** ** @(#) $Id: pager.c,v 1.17 2001/09/14 16:42:12 drh Exp $ */ #include "sqliteInt.h" #include "pager.h" #include <fcntl.h> #include <sys/stat.h> #include <unistd.h> #include <assert.h> |
︙ | ︙ | |||
99 100 101 102 103 104 105 | #define DATA_TO_PGHDR(D) (&((PgHdr*)(D))[-1]) #define PGHDR_TO_EXTRA(P) ((void*)&((char*)(&(P)[1]))[SQLITE_PAGE_SIZE]) /* ** How big to make the hash table used for locating in-memory pages ** by page number. Knuth says this should be a prime number. */ | | | 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 | #define DATA_TO_PGHDR(D) (&((PgHdr*)(D))[-1]) #define PGHDR_TO_EXTRA(P) ((void*)&((char*)(&(P)[1]))[SQLITE_PAGE_SIZE]) /* ** How big to make the hash table used for locating in-memory pages ** by page number. Knuth says this should be a prime number. */ #define N_PG_HASH 907 /* ** A open page cache is an instance of the following structure. */ struct Pager { char *zFilename; /* Name of the database file */ char *zJournal; /* Name of the journal file */ |
︙ | ︙ | |||
1057 1058 1059 1060 1061 1062 1063 | ** Commit all changes to the database and release the write lock. ** ** If the commit fails for any reason, a rollback attempt is made ** and an error code is returned. If the commit worked, SQLITE_OK ** is returned. */ int sqlitepager_commit(Pager *pPager){ | | < | | | | | | < | 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 | ** Commit all changes to the database and release the write lock. ** ** If the commit fails for any reason, a rollback attempt is made ** and an error code is returned. If the commit worked, SQLITE_OK ** is returned. */ int sqlitepager_commit(Pager *pPager){ int rc; PgHdr *pPg; if( pPager->errMask==PAGER_ERR_FULL ){ rc = sqlitepager_rollback(pPager); if( rc==SQLITE_OK ) rc = SQLITE_FULL; return rc; } if( pPager->errMask!=0 ){ rc = pager_errcode(pPager); return rc; } if( pPager->state!=SQLITE_WRITELOCK ){ return SQLITE_ERROR; } assert( pPager->jfd>=0 ); if( fsync(pPager->jfd) ){ goto commit_abort; } for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){ if( pPg->dirty==0 ) continue; rc = pager_seek(pPager->fd, (pPg->pgno-1)*SQLITE_PAGE_SIZE); if( rc!=SQLITE_OK ) goto commit_abort; rc = pager_write(pPager->fd, PGHDR_TO_DATA(pPg), SQLITE_PAGE_SIZE); if( rc!=SQLITE_OK ) goto commit_abort; } if( fsync(pPager->fd) ) goto commit_abort; rc = pager_unwritelock(pPager); pPager->dbSize = -1; return rc; /* Jump here if anything goes wrong during the commit process. |
︙ | ︙ |
Changes to src/sqliteInt.h.
︙ | ︙ | |||
19 20 21 22 23 24 25 | ** Author contact information: ** drh@hwaci.com ** http://www.hwaci.com/drh/ ** ************************************************************************* ** Internal interface definitions for SQLite. ** | | > > > > > > > | 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | ** Author contact information: ** drh@hwaci.com ** http://www.hwaci.com/drh/ ** ************************************************************************* ** Internal interface definitions for SQLite. ** ** @(#) $Id: sqliteInt.h,v 1.46 2001/09/14 16:42:12 drh Exp $ */ #include "sqlite.h" #include "vdbe.h" #include "parse.h" #include "btree.h" #include <stdio.h> #include <stdlib.h> #include <string.h> #include <assert.h> /* ** The maximum number of in-memory pages to use for the main database ** table and for temporary tables. */ #define MAX_PAGES 150 #define TEMP_PAGES 50 /* ** The paging system deals with 32-bit integers. */ typedef unsigned int u32; /* ** If memory allocation problems are found, recompile with |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
37 38 39 40 41 42 43 | ** inplicit conversion from one type to the other occurs as necessary. ** ** Most of the code in this file is taken up by the sqliteVdbeExec() ** function which does the work of interpreting a VDBE program. ** But other routines are also provided to help in building up ** a program instruction by instruction. ** | | | 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | ** inplicit conversion from one type to the other occurs as necessary. ** ** Most of the code in this file is taken up by the sqliteVdbeExec() ** function which does the work of interpreting a VDBE program. ** But other routines are also provided to help in building up ** a program instruction by instruction. ** ** $Id: vdbe.c,v 1.66 2001/09/14 16:42:12 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> #include <unistd.h> /* ** SQL is translated into a sequence of instructions to be |
︙ | ︙ | |||
2005 2006 2007 2008 2009 2010 2011 | } } VERIFY( if( i<0 ) goto bad_instruction; ) if( i>=p->nCursor ){ int j; p->aCsr = sqliteRealloc( p->aCsr, (i+1)*sizeof(Cursor) ); if( p->aCsr==0 ){ p->nCursor = 0; goto no_mem; } | | > > | 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 | } } VERIFY( if( i<0 ) goto bad_instruction; ) if( i>=p->nCursor ){ int j; p->aCsr = sqliteRealloc( p->aCsr, (i+1)*sizeof(Cursor) ); if( p->aCsr==0 ){ p->nCursor = 0; goto no_mem; } for(j=p->nCursor; j<=i; j++){ memset(&p->aCsr[j], 0, sizeof(Cursor)); } p->nCursor = i+1; }else if( p->aCsr[i].pCursor ){ sqliteBtreeCloseCursor(p->aCsr[i].pCursor); } memset(&p->aCsr[i], 0, sizeof(Cursor)); do{ rc = sqliteBtreeCursor(pBt, p2, &p->aCsr[i].pCursor); |
︙ | ︙ | |||
2048 2049 2050 2051 2052 2053 2054 | int i = pOp->p1; Cursor *pCx; VERIFY( if( i<0 ) goto bad_instruction; ) if( i>=p->nCursor ){ int j; p->aCsr = sqliteRealloc( p->aCsr, (i+1)*sizeof(Cursor) ); if( p->aCsr==0 ){ p->nCursor = 0; goto no_mem; } | | > > | | 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 | int i = pOp->p1; Cursor *pCx; VERIFY( if( i<0 ) goto bad_instruction; ) if( i>=p->nCursor ){ int j; p->aCsr = sqliteRealloc( p->aCsr, (i+1)*sizeof(Cursor) ); if( p->aCsr==0 ){ p->nCursor = 0; goto no_mem; } for(j=p->nCursor; j<=i; j++){ memset(&p->aCsr[j], 0, sizeof(Cursor)); } p->nCursor = i+1; }else if( p->aCsr[i].pCursor ){ sqliteBtreeCloseCursor(p->aCsr[i].pCursor); } pCx = &p->aCsr[i]; memset(pCx, 0, sizeof(*pCx)); rc = sqliteBtreeOpen(0, 0, TEMP_PAGES, &pCx->pBt); if( rc==SQLITE_OK ){ rc = sqliteBtreeCursor(pCx->pBt, 2, &pCx->pCursor); } if( rc==SQLITE_OK ){ rc = sqliteBtreeBeginTrans(pCx->pBt); } break; |
︙ | ︙ | |||
2200 2201 2202 2203 2204 2205 2206 | ** Get a new integer record number used as the key to a table. ** The record number is not previous used by the database file ** associated with cursor P1. The new record number pushed ** onto the stack. */ case OP_NewRecno: { int i = pOp->p1; | | > > > > > | | | > > > > > > | 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 | ** Get a new integer record number used as the key to a table. ** The record number is not previous used by the database file ** associated with cursor P1. The new record number pushed ** onto the stack. */ case OP_NewRecno: { int i = pOp->p1; int v = 0; if( VERIFY( i<0 || i>=p->nCursor || ) p->aCsr[i].pCursor==0 ){ v = 0; }else{ int res, rx, cnt; static int x = 0; union { char zBuf[sizeof(int)]; int i; } ux; cnt = 0; do{ if( x==0 || cnt>5 ){ x = sqliteRandomInteger(); }else{ x += sqliteRandomByte() + 1; } if( x==0 ) continue; ux.zBuf[3] = x&0xff; ux.zBuf[2] = (x>>8)&0xff; ux.zBuf[1] = (x>>16)&0xff; ux.zBuf[0] = (x>>24)&0xff; v = ux.i; rx = sqliteBtreeMoveto(p->aCsr[i].pCursor, &v, sizeof(v), &res); cnt++; }while( cnt<10 && rx==SQLITE_OK && res==0 ); } VERIFY( NeedStack(p, p->tos+1); ) p->tos++; aStack[p->tos].i = v; |
︙ | ︙ |
Changes to test/all.test.
︙ | ︙ | |||
18 19 20 21 22 23 24 | # Author contact information: # drh@hwaci.com # http://www.hwaci.com/drh/ # #*********************************************************************** # This file runs all tests. # | | | | 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | # Author contact information: # drh@hwaci.com # http://www.hwaci.com/drh/ # #*********************************************************************** # This file runs all tests. # # $Id: all.test,v 1.9 2001/09/14 16:42:13 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl rename finish_test really_finish_test proc finish_test {} {memleak_check} if {[file exists ./sqlite_test_count]} { set COUNT [exec cat ./sqlite_test_count] } else { set COUNT 3 } # LeakList will hold a list of the number of unfreed mallocs after # each round of the test. This number should be constant. If it # grows, it may mean there is a memory leak in the library. # set LeakList {} for {set Counter 0} {$Counter<$COUNT && $nErr==0} {incr Counter} { foreach testfile [lsort -dictionary [glob $testdir/*.test]] { if {[file tail $testfile]=="all.test"} continue if {[file tail $testfile]=="malloc.test"} continue source $testfile } if {[info exists Leak]} { lappend LeakList $Leak |
︙ | ︙ | |||
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | incr ::nTest foreach x $LeakList { if {$x!=[lindex $LeakList 0]} { puts " failed!" puts "Expected: all values to be the same" puts " Got: $LeakList" incr ::nErr break } } puts " Ok" } if {[file readable $testdir/malloc.test]} { source $testdir/malloc.test } really_finish_test | > | 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | incr ::nTest foreach x $LeakList { if {$x!=[lindex $LeakList 0]} { puts " failed!" puts "Expected: all values to be the same" puts " Got: $LeakList" incr ::nErr lappend ::failList memory-leak-test break } } puts " Ok" } if {[file readable $testdir/malloc.test]} { source $testdir/malloc.test } really_finish_test |
Changes to test/btree2.test.
︙ | ︙ | |||
19 20 21 22 23 24 25 | # drh@hwaci.com # http://www.hwaci.com/drh/ # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this script is btree database backend # | | | 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | # drh@hwaci.com # http://www.hwaci.com/drh/ # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this script is btree database backend # # $Id: btree2.test,v 1.6 2001/09/14 16:42:13 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl if {[info commands btree_open]!=""} { |
︙ | ︙ | |||
284 285 286 287 288 289 290 | # Repeat this test sequence on database of various sizes # set testno 2 foreach {N L} { 10 2 50 2 200 3 | < > | 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 | # Repeat this test sequence on database of various sizes # set testno 2 foreach {N L} { 10 2 50 2 200 3 } { # 2000 5 puts "**** N=$N L=$L ****" set hash [md5file test2.bt] do_test btree2-$testno.1 [subst -nocommands { set ::c2 [btree_cursor $::b 2] set ::c3 [btree_cursor $::b 3] set ::c4 [btree_cursor $::b 4] set ::c5 [btree_cursor $::b 5] |
︙ | ︙ |
Changes to test/tester.tcl.
︙ | ︙ | |||
19 20 21 22 23 24 25 | # drh@hwaci.com # http://www.hwaci.com/drh/ # #*********************************************************************** # This file implements some common TCL routines used for regression # testing the SQLite library # | | | 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | # drh@hwaci.com # http://www.hwaci.com/drh/ # #*********************************************************************** # This file implements some common TCL routines used for regression # testing the SQLite library # # $Id: tester.tcl,v 1.17 2001/09/14 16:42:13 drh Exp $ # Make sure tclsqlite was compiled correctly. Abort now with an # error message if not. # if {[sqlite -tcl-uses-utf]} { if {"\u1234"=="u1234"} { puts stderr "***** BUILD PROBLEM *****" |
︙ | ︙ | |||
64 65 66 67 68 69 70 71 72 73 74 75 76 77 | # Set the test counters to zero # set nErr 0 set nTest 0 set nProb 0 set skip_test 0 # Invoke the do_test procedure to run a single test # proc do_test {name cmd expected} { global argv nErr nTest skip_test if {$skip_test} { set skip_test 0 | > | 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | # Set the test counters to zero # set nErr 0 set nTest 0 set nProb 0 set skip_test 0 set failList {} # Invoke the do_test procedure to run a single test # proc do_test {name cmd expected} { global argv nErr nTest skip_test if {$skip_test} { set skip_test 0 |
︙ | ︙ | |||
91 92 93 94 95 96 97 | if {!$go} return incr nTest puts -nonewline $name... flush stdout if {[catch {uplevel #0 "$cmd;\n"} result]} { puts "\nError: $result" incr nErr | > | > | | 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | if {!$go} return incr nTest puts -nonewline $name... flush stdout if {[catch {uplevel #0 "$cmd;\n"} result]} { puts "\nError: $result" incr nErr lappend ::failList $name if {$nErr>10} {puts "*** Giving up..."; finalize_testing} } elseif {[string compare $result $expected]} { puts "\nExpected: \[$expected\]\n Got: \[$result\]" incr nErr lappend ::failList $name if {$nErr>10} {puts "*** Giving up..."; finalize_testing} } else { puts " Ok" } } # Invoke this procedure on a test that is probabilistic # and might fail sometimes. |
︙ | ︙ | |||
156 157 158 159 160 161 162 163 | set ::Leak [expr {[lindex $r 0]-[lindex $r 1]}] } } # Run this routine last # proc finish_test {} { global nTest nErr nProb | > > > | > | 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 | set ::Leak [expr {[lindex $r 0]-[lindex $r 1]}] } } # Run this routine last # proc finish_test {} { finalize_testing } proc finalize_testing {} { global nTest nErr nProb if {$nErr==0} memleak_check catch {db close} puts "$nErr errors out of $nTest tests" puts "Failures on these tests: $::failList" if {$nProb>0} { puts "$nProb probabilistic tests also failed, but this does" puts "not necessarily indicate a malfunction." } exit [expr {$nErr>0}] } |
︙ | ︙ |
Changes to tool/lempar.c.
︙ | ︙ | |||
185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 | static char *yyTokenName[] = { %% }; #define YYTRACE(X) if( yyTraceFILE ) fprintf(yyTraceFILE,"%sReduce [%s].\n",yyTracePrompt,X); #else #define YYTRACE(X) #endif /* ** This function returns the symbolic name associated with a token ** value. */ const char *ParseTokenName(int tokenType){ if( tokenType>0 && tokenType<(sizeof(yyTokenName)/sizeof(yyTokenName[0])) ){ return yyTokenName[tokenType]; }else{ return "Unknown"; } } /* ** This function allocates a new parser. ** The only argument is a pointer to a function which works like ** malloc. ** | > > > > > | 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 | static char *yyTokenName[] = { %% }; #define YYTRACE(X) if( yyTraceFILE ) fprintf(yyTraceFILE,"%sReduce [%s].\n",yyTracePrompt,X); #else #define YYTRACE(X) #endif /* ** This function returns the symbolic name associated with a token ** value. */ const char *ParseTokenName(int tokenType){ #ifndef NDEBUG if( tokenType>0 && tokenType<(sizeof(yyTokenName)/sizeof(yyTokenName[0])) ){ return yyTokenName[tokenType]; }else{ return "Unknown"; } #else return ""; #endif } /* ** This function allocates a new parser. ** The only argument is a pointer to a function which works like ** malloc. ** |
︙ | ︙ |