diff --git a/manifest b/manifest index 97c0748af1..5c6840dc7b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Updates\sto\sthe\sdocumentation.\s\sChanged\sversion\snumber\sto\s2.4.0-beta1\s(CVS\s417) -D 2002-03-04T02:26:16 +C Add\sthe\sability\sto\sturn\sof\scalls\sto\sfsync()\susing\sthe\s"synchronous"\spragma.\nIncreased\sthe\sdefault\scache\ssize\sfrom\s100\sto\s2000\sand\smade\sthe\s"cache_size"\npragma\spersistent.\s(CVS\s418) +D 2002-03-05T01:11:13 F Makefile.in 50f1b3351df109b5774771350d8c1b8d3640130d F Makefile.template 89e373b2dad0321df00400fa968dc14b61a03296 F README a4c0ba11354ef6ba0776b400d057c59da47a4cc0 @@ -21,27 +21,27 @@ F sqlite.1 2e2bb0529ef468ade9e4322bd609d0695fb9ded9 F src/TODO af7f3cab0228e34149cf98e073aa83d45878e7e6 F src/btree.c d25ea795a0f7017bc2099c437e6cc01d4c31b22d F src/btree.h 8abeabfe6e0b1a990b64fa457592a6482f6674f3 -F src/build.c e11b0daa79ba894c7476c33372b1dc42b13471e6 +F src/build.c 0f3c6b6482e0b74284b22661de1b813a0bfb0197 F src/delete.c 577da499162291c1855f0b304b211bffcf9da945 F src/expr.c e12ca550536c0bae7a3acef49dfa3068fe5f0900 F src/func.c 87516e7dc37190c24af77593931a5d09d797520a F src/hash.c cc259475e358baaf299b00a2c7370f2b03dda892 F src/hash.h dca065dda89d4575f3176e75e9a3dc0f4b4fb8b9 F src/insert.c 42bfd145efd428d7e5f200dd49ea0b816fc30d79 -F src/main.c 5651146585ae613e759fcf372ee064e4940c2463 +F src/main.c 3015c23faeff1709b1528f07c0bfe839284090a8 F src/md5.c 52f677bfc590e09f71d07d7e327bd59da738d07c -F src/os.c f6bc9b7ab530346bb7fef2ed39f2f1f214bc14ea +F src/os.c db969ecd1bcb4fef01b0b541b8b17401b0eb7ed2 F src/os.h a17596ecc7f38a228b83ecdb661fb03ce44726d6 -F src/pager.c 0aa358a378c416ee0b0be5bf03fa7c35f7992c9b +F src/pager.c 41af87908cd76a50d7e22cf3c7a4d479e3c9a512 F src/pager.h feb18aab2f6dea439393f23a382699b9b1053c32 -F src/parse.y 25b794bfbed2a68d13d7d40a986a0ebe2beb3e24 +F src/parse.y f7483ccff7b8f16d3655df59775d85b62b06897e F src/printf.c 300a90554345751f26e1fc0c0333b90a66110a1d F src/random.c 19e8e00fe0df32a742f115773f57651be327cabe F src/select.c 49c78aa0c96dda036846937b516658536db98b56 F src/shell.c b3454229599246b944cdb5b95753af3fca5d8bb0 F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e F src/sqlite.h.in a9b5772604265f98f3120573ef29e37b9d917216 -F src/sqliteInt.h dde4e52e234e54e8ac9d3a1964e93c5fa6c2de15 +F src/sqliteInt.h 46f41e2f4cf90cdbe002f6b4143ae3f16ae0b872 F src/table.c 203a09d5d0009eeeb1f670370d52b4ce163a3b52 F src/tclsqlite.c b9cf346e95291cb4c4f1bf5ac1d77db6b8ad023d F src/test1.c 33efd350dca27c52c58c553c04fd3a6a51f13c1f @@ -51,7 +51,7 @@ F src/threadtest.c 81f0598e0f031c1bd506af337fdc1b7e8dff263f F src/tokenize.c 4b5d30590a744b9bb5605a92d1f620ab2e7e75af F src/update.c 7dd714a6a7fa47f849ebb36b6d915974d6c6accb F src/util.c 00a35b421c92ae0d7cfa51bd87f7d4995f464d19 -F src/vdbe.c 4989cd3e6f4f699c9b08cd1980d1b588cede5c1f +F src/vdbe.c 0b634bbe3d1a770136b9f7324804bb55903a9b17 F src/vdbe.h f9be1f6e9a336c3ff4d14ea7489ee976e07460cc F src/where.c 34d91fd5d822c2663caeb023f72d60df316ebf29 F test/all.test 7a8a8a7a579ed2bb4d8976d55402f21eacd58049 @@ -108,11 +108,12 @@ F tool/opNames.awk 5ba1f48aa854ee3b7c3d2b54233665bc3e649ea2 F tool/opcodeDoc.awk b3a2a3d5d3075b8bd90b7afe24283efdd586659c F tool/renumberOps.awk 6d067177ad5f8d711b79577b462da9b3634bd0a9 F tool/report1.txt 9eae07f26a8fc53889b45fc833a66a33daa22816 +F tool/speedtest.tcl 31a2f06e3d2153f4311b13cd6fd5e19b7adc8373 F www/arch.fig d5f9752a4dbf242e9cfffffd3f5762b6c63b3bcf F www/arch.png 82ef36db1143828a7abc88b1e308a5f55d4336f4 F www/arch.tcl 72a0c80e9054cc7025a50928d28d9c75c02c2b8b F www/c_interface.tcl 567cda531aac9d68a61ef02e26c6b202bd856db2 -F www/changes.tcl cdd351b0f358bc23ca6243f3ca52c35ca1bede26 +F www/changes.tcl b43d9e32ed7af9a93c5a9b7321abe2ee6a8f4ea9 F www/conflict.tcl 81dd21f9a679e60aae049e9dd8ab53d59570cda2 F www/crosscompile.tcl 3622ebbe518927a3854a12de51344673eb2dd060 F www/download.tcl a6d75b8b117cd33dcb090bef7e80d7556d28ebe0 @@ -127,7 +128,7 @@ F www/speed.tcl 83457b2bf6bb430900bd48ca3dd98264d9a916a5 F www/sqlite.tcl 8b5884354cb615049aed83039f8dfe1552a44279 F www/tclsqlite.tcl 829b393d1ab187fd7a5e978631b3429318885c49 F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218 -P 813077623087ffc6cd506f57cf6d1e3d9239f806 -R fe676fb38cbe5a2068c89e56308a155d +P 36a8fe0ad0ee2a67afafc04125dcc085ec1b5a13 +R e93330a0aa7a7fa6a56e7a5c31b63757 U drh -Z 9a81a81e1e363e5bb6c841e14ddef308 +Z b84940384f009522e2520b7d71139ff4 diff --git a/manifest.uuid b/manifest.uuid index 79e1438fa4..36d2035611 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -36a8fe0ad0ee2a67afafc04125dcc085ec1b5a13 \ No newline at end of file +414da4af1f4aebc3936ca339fbc7932add081912 \ No newline at end of file diff --git a/src/build.c b/src/build.c index 1642e47eb8..639ba00f7a 100644 --- a/src/build.c +++ b/src/build.c @@ -25,7 +25,7 @@ ** ROLLBACK ** PRAGMA ** -** $Id: build.c,v 1.84 2002/03/04 02:26:16 drh Exp $ +** $Id: build.c,v 1.85 2002/03/05 01:11:13 drh Exp $ */ #include "sqliteInt.h" #include @@ -423,7 +423,8 @@ void sqliteStartTable(Parse *pParse, Token *pStart, Token *pName, int isTemp){ if( !pParse->initFlag && (v = sqliteGetVdbe(pParse))!=0 ){ sqliteBeginWriteOperation(pParse); if( !isTemp ){ - sqliteVdbeAddOp(v, OP_SetCookie, db->file_format, 1); + sqliteVdbeAddOp(v, OP_Integer, db->file_format, 0); + sqliteVdbeAddOp(v, OP_SetCookie, 0, 1); sqliteVdbeAddOp(v, OP_OpenWrite, 0, 2); sqliteVdbeChangeP3(v, -1, MASTER_NAME, P3_STATIC); sqliteVdbeAddOp(v, OP_NewRecno, 0, 0); @@ -794,7 +795,8 @@ void sqliteEndTable(Parse *pParse, Token *pEnd, Select *pSelect){ sqliteVdbeAddOp(v, OP_MakeRecord, 5, 0); sqliteVdbeAddOp(v, OP_PutIntKey, 0, 0); changeCookie(db); - sqliteVdbeAddOp(v, OP_SetCookie, db->next_cookie, 0); + sqliteVdbeAddOp(v, OP_Integer, db->next_cookie, 0); + sqliteVdbeAddOp(v, OP_SetCookie, 0, 0); sqliteVdbeAddOp(v, OP_Close, 0, 0); } if( pSelect ){ @@ -1023,7 +1025,8 @@ void sqliteDropTable(Parse *pParse, Token *pName, int isView){ { OP_Ne, 0, ADDR(8), 0}, { OP_Delete, 0, 0, 0}, { OP_Next, 0, ADDR(4), 0}, /* 8 */ - { OP_SetCookie, 0, 0, 0}, /* 9 */ + { OP_Integer, 0, 0, 0}, /* 9 */ + { OP_SetCookie, 0, 0, 0}, { OP_Close, 0, 0, 0}, }; Index *pIdx; @@ -1337,7 +1340,8 @@ void sqliteCreateIndex( if( pTable!=0 ){ if( !isTemp ){ changeCookie(db); - sqliteVdbeAddOp(v, OP_SetCookie, db->next_cookie, 0); + sqliteVdbeAddOp(v, OP_Integer, db->next_cookie, 0); + sqliteVdbeAddOp(v, OP_SetCookie, 0, 0); sqliteVdbeAddOp(v, OP_Close, 0, 0); } sqliteEndWriteOperation(pParse); @@ -1387,7 +1391,8 @@ void sqliteDropIndex(Parse *pParse, Token *pName){ { OP_Next, 0, ADDR(4), 0}, { OP_Goto, 0, ADDR(10),0}, { OP_Delete, 0, 0, 0}, /* 9 */ - { OP_SetCookie, 0, 0, 0}, /* 10 */ + { OP_Integer, 0, 0, 0}, /* 10 */ + { OP_SetCookie, 0, 0, 0}, { OP_Close, 0, 0, 0}, }; int base; @@ -1732,8 +1737,58 @@ void sqlitePragma(Parse *pParse, Token *pLeft, Token *pRight, int minusFlag){ } if( sqliteStrICmp(zLeft,"cache_size")==0 ){ - int size = atoi(zRight); - sqliteBtreeSetCacheSize(db->pBe, size); + static VdbeOp getCacheSize[] = { + { OP_ReadCookie, 0, 2, 0}, + { OP_AbsValue, 0, 0, 0}, + { OP_ColumnCount, 1, 0, 0}, + { OP_ColumnName, 0, 0, "cache_size"}, + { OP_Callback, 1, 0, 0}, + }; + Vdbe *v = sqliteGetVdbe(pParse); + if( v==0 ) return; + if( pRight->z==pLeft->z ){ + sqliteVdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize); + }else{ + int addr; + int size = atoi(zRight); + if( size<0 ) size = -size; + sqliteBeginWriteOperation(pParse); + sqliteVdbeAddOp(v, OP_Integer, size, 0); + sqliteVdbeAddOp(v, OP_ReadCookie, 0, 2); + addr = sqliteVdbeAddOp(v, OP_Integer, 0, 0); + sqliteVdbeAddOp(v, OP_Ge, 0, addr+3); + sqliteVdbeAddOp(v, OP_Negative, 0, 0); + sqliteVdbeAddOp(v, OP_SetCookie, 0, 2); + sqliteEndWriteOperation(pParse); + } + }else + + if( sqliteStrICmp(zLeft,"synchronous")==0 ){ + static VdbeOp getSync[] = { + { OP_Integer, 0, 0, 0}, + { OP_ReadCookie, 0, 2, 0}, + { OP_Integer, 0, 0, 0}, + { OP_Lt, 0, 5, 0}, + { OP_AddImm, 1, 0, 0}, + { OP_ColumnCount, 1, 0, 0}, + { OP_ColumnName, 0, 0, "synchronous"}, + { OP_Callback, 1, 0, 0}, + }; + Vdbe *v = sqliteGetVdbe(pParse); + if( v==0 ) return; + if( pRight->z==pLeft->z ){ + sqliteVdbeAddOpList(v, ArraySize(getSync), getSync); + }else{ + int addr; + sqliteBeginWriteOperation(pParse); + sqliteVdbeAddOp(v, OP_ReadCookie, 0, 2); + sqliteVdbeAddOp(v, OP_AbsValue, 0, 0); + if( !getBoolean(zRight) ){ + sqliteVdbeAddOp(v, OP_Negative, 0, 0); + } + sqliteVdbeAddOp(v, OP_SetCookie, 0, 2); + sqliteEndWriteOperation(pParse); + } }else if( sqliteStrICmp(zLeft, "vdbe_trace")==0 ){ diff --git a/src/main.c b/src/main.c index 8ad0d18d32..62f0952a3a 100644 --- a/src/main.c +++ b/src/main.c @@ -14,7 +14,7 @@ ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** -** $Id: main.c,v 1.66 2002/02/28 00:41:11 drh Exp $ +** $Id: main.c,v 1.67 2002/03/05 01:11:14 drh Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -42,6 +42,13 @@ static int sqliteOpenCb(void *pDb, int argc, char **argv, char **azColName){ assert( argc==4 ); switch( argv[0][0] ){ + case 'c': { /* Recommended pager cache size */ + int size = atoi(argv[3]); + if( size!=0 ){ + sqliteBtreeSetCacheSize(db->pBe, size); + } + break; + } case 'f': { /* File format */ db->file_format = atoi(argv[3]); break; @@ -176,6 +183,14 @@ static int sqliteInit(sqlite *db, char **pzErrMsg){ { OP_ReadCookie, 0, 1, 0}, { OP_Callback, 4, 0, 0}, + /* Send the recommended pager cache size to the callback routine + */ + { OP_String, 0, 0, "cache-size"}, + { OP_String, 0, 0, 0}, + { OP_String, 0, 0, 0}, + { OP_ReadCookie, 0, 2, 0}, + { OP_Callback, 4, 0, 0}, + /* Send the initial schema cookie to the callback */ { OP_String, 0, 0, "schema_cookie"}, @@ -192,45 +207,45 @@ static int sqliteInit(sqlite *db, char **pzErrMsg){ */ { OP_ReadCookie, 0, 1, 0}, { OP_Integer, 2, 0, 0}, - { OP_Lt, 0, 23, 0}, + { OP_Lt, 0, 28, 0}, /* This is the code for doing a single scan through the SQLITE_MASTER ** table. This code runs for format 2 and greater. */ - { OP_Rewind, 0, 21, 0}, - { OP_Column, 0, 0, 0}, /* 15 */ + { OP_Rewind, 0, 26, 0}, + { OP_Column, 0, 0, 0}, /* 20 */ { OP_Column, 0, 1, 0}, { OP_Column, 0, 3, 0}, { OP_Column, 0, 4, 0}, { OP_Callback, 4, 0, 0}, - { OP_Next, 0, 15, 0}, - { OP_Close, 0, 0, 0}, /* 21 */ + { OP_Next, 0, 20, 0}, + { OP_Close, 0, 0, 0}, /* 26 */ { OP_Halt, 0, 0, 0}, /* This is the code for doing two passes through SQLITE_MASTER. This ** code runs for file format 1. */ - { OP_Rewind, 0, 43, 0}, /* 23 */ - { OP_Column, 0, 0, 0}, /* 24 */ + { OP_Rewind, 0, 48, 0}, /* 28 */ + { OP_Column, 0, 0, 0}, /* 29 */ { OP_String, 0, 0, "table"}, - { OP_Ne, 0, 32, 0}, + { OP_Ne, 0, 37, 0}, { OP_Column, 0, 0, 0}, { OP_Column, 0, 1, 0}, { OP_Column, 0, 3, 0}, { OP_Column, 0, 4, 0}, { OP_Callback, 4, 0, 0}, - { OP_Next, 0, 24, 0}, /* 32 */ - { OP_Rewind, 0, 43, 0}, /* 33 */ - { OP_Column, 0, 0, 0}, /* 34 */ + { OP_Next, 0, 29, 0}, /* 37 */ + { OP_Rewind, 0, 48, 0}, /* 38 */ + { OP_Column, 0, 0, 0}, /* 39 */ { OP_String, 0, 0, "index"}, - { OP_Ne, 0, 42, 0}, + { OP_Ne, 0, 47, 0}, { OP_Column, 0, 0, 0}, { OP_Column, 0, 1, 0}, { OP_Column, 0, 3, 0}, { OP_Column, 0, 4, 0}, { OP_Callback, 4, 0, 0}, - { OP_Next, 0, 34, 0}, /* 42 */ - { OP_Close, 0, 0, 0}, /* 43 */ + { OP_Next, 0, 39, 0}, /* 47 */ + { OP_Close, 0, 0, 0}, /* 48 */ { OP_Halt, 0, 0, 0}, }; diff --git a/src/os.c b/src/os.c index ae1368c284..0467545822 100644 --- a/src/os.c +++ b/src/os.c @@ -43,6 +43,20 @@ # include #endif +/* +** Macros for performance tracing. Normally turned off +*/ +#if 0 +static int last_page = 0; +#define SEEK(X) last_page=(X) +#define TRACE1(X) fprintf(stderr,X) +#define TRACE2(X,Y) fprintf(stderr,X,Y) +#else +#define SEEK(X) +#define TRACE1(X) +#define TRACE2(X,Y) +#endif + #if OS_UNIX /* @@ -477,6 +491,7 @@ int sqliteOsRead(OsFile *id, void *pBuf, int amt){ #if OS_UNIX int got; SimulateIOError(SQLITE_IOERR); + TRACE2("READ %d\n", last_page); got = read(id->fd, pBuf, amt); if( got<0 ) got = 0; return got==amt ? SQLITE_OK : SQLITE_IOERR; @@ -499,6 +514,7 @@ int sqliteOsWrite(OsFile *id, const void *pBuf, int amt){ #if OS_UNIX int wrote; SimulateIOError(SQLITE_IOERR); + TRACE2("WRITE %d\n", last_page); wrote = write(id->fd, pBuf, amt); if( wrotefd, offset, SEEK_SET); return SQLITE_OK; @@ -532,6 +549,7 @@ int sqliteOsSeek(OsFile *id, int offset){ */ int sqliteOsSync(OsFile *id){ SimulateIOError(SQLITE_IOERR); + TRACE1("SYNC\n"); #if OS_UNIX return fsync(id->fd)==0 ? SQLITE_OK : SQLITE_IOERR; #endif diff --git a/src/pager.c b/src/pager.c index b69b283282..de332cba02 100644 --- a/src/pager.c +++ b/src/pager.c @@ -18,7 +18,7 @@ ** file simultaneously, or one process from reading the database while ** another is writing. ** -** @(#) $Id: pager.c,v 1.41 2002/03/02 20:41:59 drh Exp $ +** @(#) $Id: pager.c,v 1.42 2002/03/05 01:11:14 drh Exp $ */ #include "sqliteInt.h" #include "pager.h" @@ -93,7 +93,7 @@ struct PgHdr { ** 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 373 +#define N_PG_HASH 2003 /* ** A open page cache is an instance of the following structure. @@ -103,8 +103,6 @@ struct Pager { char *zJournal; /* Name of the journal file */ OsFile fd, jfd; /* File descriptors for database and journal */ OsFile cpfd; /* File descriptor for the checkpoint journal */ - int journalOpen; /* True if journal file descriptors is valid */ - int ckptOpen; /* True if the checkpoint journal is open */ int dbSize; /* Number of pages in the file */ int origDbSize; /* dbSize before the current change */ int ckptSize, ckptJSize; /* Size of database and journal at ckpt_begin() */ @@ -114,13 +112,16 @@ struct Pager { int nRef; /* Number of in-memory pages with PgHdr.nRef>0 */ int mxPage; /* Maximum number of pages to hold in cache */ int nHit, nMiss, nOvfl; /* Cache hits, missing, and LRU overflows */ - unsigned char state; /* SQLITE_UNLOCK, _READLOCK or _WRITELOCK */ - unsigned char errMask; /* One of several kinds of errors */ - unsigned char tempFile; /* zFilename is a temporary file */ - unsigned char readOnly; /* True for a read-only database */ - unsigned char needSync; /* True if an fsync() is needed on the journal */ - unsigned char *aInJournal; /* One bit for each page in the database file */ - unsigned char *aInCkpt; /* One bit for each page in the database */ + u8 journalOpen; /* True if journal file descriptors is valid */ + u8 ckptOpen; /* True if the checkpoint journal is open */ + u8 noSync; /* Do not sync the journal if true */ + u8 state; /* SQLITE_UNLOCK, _READLOCK or _WRITELOCK */ + u8 errMask; /* One of several kinds of errors */ + u8 tempFile; /* zFilename is a temporary file */ + u8 readOnly; /* True for a read-only database */ + u8 needSync; /* True if an fsync() is needed on the journal */ + u8 *aInJournal; /* One bit for each page in the database file */ + u8 *aInCkpt; /* One bit for each page in the database */ PgHdr *pFirst, *pLast; /* List of free pages */ PgHdr *pAll; /* List of all pages */ PgHdr *aHash[N_PG_HASH]; /* Hash table to map page number of PgHdr */ @@ -435,6 +436,12 @@ end_ckpt_playback: ** Change the maximum number of in-memory pages that are allowed. */ void sqlitepager_set_cachesize(Pager *pPager, int mxPage){ + if( mxPage>=0 ){ + pPager->noSync = 0; + }else{ + pPager->noSync = 1; + mxPage = -mxPage; + } if( mxPage>10 ){ pPager->mxPage = mxPage; } @@ -800,9 +807,8 @@ int sqlitepager_get(Pager *pPager, Pgno pgno, void **ppPage){ /* Recycle an older page. First locate the page to be recycled. ** Try to find one that is not dirty and is near the head of ** of the free list */ - int cnt = pPager->mxPage/2; pPg = pPager->pFirst; - while( pPg->dirty && 0pNextFree ){ + while( pPg && pPg->dirty ){ pPg = pPg->pNextFree; } @@ -818,7 +824,7 @@ int sqlitepager_get(Pager *pPager, Pgno pgno, void **ppPage){ ** near future. That is way we write all dirty pages after a ** sync. */ - if( pPg==0 || pPg->dirty ){ + if( pPg==0 ){ int rc = syncAllPages(pPager); if( rc!=0 ){ sqlitepager_rollback(pPager); @@ -1081,7 +1087,7 @@ int sqlitepager_write(void *pData){ } assert( pPager->aInJournal!=0 ); pPager->aInJournal[pPg->pgno/8] |= 1<<(pPg->pgno&7); - pPager->needSync = 1; + pPager->needSync = !pPager->noSync; pPg->inJournal = 1; if( pPager->ckptOpen ){ pPager->aInCkpt[pPg->pgno/8] |= 1<<(pPg->pgno&7); @@ -1209,7 +1215,9 @@ int sqlitepager_commit(Pager *pPager){ rc = sqliteOsWrite(&pPager->fd, PGHDR_TO_DATA(pPg), SQLITE_PAGE_SIZE); if( rc!=SQLITE_OK ) goto commit_abort; } - if( sqliteOsSync(&pPager->fd)!=SQLITE_OK ) goto commit_abort; + if( !pPager->noSync && sqliteOsSync(&pPager->fd)!=SQLITE_OK ){ + goto commit_abort; + } rc = pager_unwritelock(pPager); pPager->dbSize = -1; return rc; diff --git a/src/parse.y b/src/parse.y index 7a2f13b106..fc521a5f5a 100644 --- a/src/parse.y +++ b/src/parse.y @@ -14,7 +14,7 @@ ** the parser. Lemon will also generate a header file containing ** numeric codes for all of the tokens. ** -** @(#) $Id: parse.y,v 1.55 2002/03/03 23:06:01 drh Exp $ +** @(#) $Id: parse.y,v 1.56 2002/03/05 01:11:14 drh Exp $ */ %token_prefix TK_ %token_type {Token} @@ -581,7 +581,7 @@ cmd ::= PRAGMA ids(X) EQ ON(Y). {sqlitePragma(pParse,&X,&Y,0);} cmd ::= PRAGMA ids(X) EQ plus_num(Y). {sqlitePragma(pParse,&X,&Y,0);} cmd ::= PRAGMA ids(X) EQ minus_num(Y). {sqlitePragma(pParse,&X,&Y,1);} cmd ::= PRAGMA ids(X) LP ids(Y) RP. {sqlitePragma(pParse,&X,&Y,0);} -cmd ::= PRAGMA(Y) ids(X). {sqlitePragma(pParse,&X,&Y,0);} +cmd ::= PRAGMA ids(X). {sqlitePragma(pParse,&X,&X,0);} plus_num(A) ::= plus_opt number(X). {A = X;} minus_num(A) ::= MINUS number(X). {A = X;} number(A) ::= INTEGER(X). {A = X;} diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 4dd693c325..3520a94e93 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.101 2002/03/03 23:06:02 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.102 2002/03/05 01:11:14 drh Exp $ */ #include "sqlite.h" #include "hash.h" @@ -27,8 +27,8 @@ ** The maximum number of in-memory pages to use for the main database ** table and for temporary tables. */ -#define MAX_PAGES 100 -#define TEMP_PAGES 25 +#define MAX_PAGES 2000 +#define TEMP_PAGES 500 /* ** Integers of known sizes. These typedefs might change for architectures diff --git a/src/vdbe.c b/src/vdbe.c index 1d8989740b..f5ab9161cf 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -30,7 +30,7 @@ ** But other routines are also provided to help in building up ** a program instruction by instruction. ** -** $Id: vdbe.c,v 1.130 2002/03/03 02:49:51 drh Exp $ +** $Id: vdbe.c,v 1.131 2002/03/05 01:11:14 drh Exp $ */ #include "sqliteInt.h" #include @@ -2555,7 +2555,8 @@ case OP_Rollback: { ** ** If P2>0, then read global database parameter number P2. There is ** a small fixed number of global database parameters. P2==1 is the -** database version number. Other parameters are currently unused. +** database version number. P2==2 is the recommended pager cache size. +** Other parameters are currently unused. ** ** There must be a read-lock on the database (either a transaction ** must be started or there must be an open cursor) before @@ -2572,11 +2573,12 @@ case OP_ReadCookie: { break; } -/* Opcode: SetCookie P1 P2 * +/* Opcode: SetCookie * P2 * ** ** When P2==0, ** this operation changes the value of the schema cookie on the database. -** The new value is P1. When P2>0, the value of global database parameter +** The new value is top of the stack. +** When P2>0, the value of global database parameter ** number P2 is changed. See ReadCookie for more information about ** global database parametes. ** @@ -2589,11 +2591,14 @@ case OP_ReadCookie: { case OP_SetCookie: { int aMeta[SQLITE_N_BTREE_META]; assert( pOp->p2tos<0 ) goto not_enough_stack; ) + Integerify(p, p->tos) rc = sqliteBtreeGetMeta(pBt, aMeta); if( rc==SQLITE_OK ){ - aMeta[1+pOp->p2] = pOp->p1; + aMeta[1+pOp->p2] = aStack[p->tos].i; rc = sqliteBtreeUpdateMeta(pBt, aMeta); } + POPSTACK; break; } diff --git a/tool/speedtest.tcl b/tool/speedtest.tcl new file mode 100644 index 0000000000..8de470249c --- /dev/null +++ b/tool/speedtest.tcl @@ -0,0 +1,228 @@ +#!/usr/bin/tclsh +# +# Run this script using TCLSH to do a speed comparison between +# various versions of SQLite and PostgreSQL and MySQL +# + +# Run a test +# +set cnt 0 +proc runtest {title sqlfile} { + global cnt + incr cnt + puts "

Test $cnt: $title

" + set fd [open $sqlfile r] + set sql [string trim [read $fd [file size $sqlfile]]] + close $fd + set sx [split $sql \n] + set n [llength $sx] + if {$n>8} { + set sql {} + for {set i 0} {$i<3} {incr i} {append sql [lindex $sx $i]
\n} + append sql "... [expr {$n-6}] lines omitted
\n" + for {set i [expr {$n-3}]} {$i<$n} {incr i} { + append sql [lindex $sx $i]
\n + } + } else { + regsub -all \n [string trim $sql]
sql + } + puts "
" + puts "$sql" + puts "
" + set format {} + set t [time "exec psql drh <$sqlfile" 1] + set t [expr {[lindex $t 0]/1000000.0}] + puts [format $format PostgreSQL: $t] + set t [time "exec mysql drh <$sqlfile" 1] + set t [expr {[lindex $t 0]/1000000.0}] + puts [format $format MySQL: $t] +# set t [time "exec ./sqlite232 s232.db <$sqlfile" 1] +# set t [expr {[lindex $t 0]/1000000.0}] +# puts [format $format {SQLite 2.3.2:} $t] +# set t [time "exec ./sqlite-100 s100.db <$sqlfile" 1] +# set t [expr {[lindex $t 0]/1000000.0}] +# puts [format $format {SQLite 2.4 (cache=100):} $t] + set t [time "exec ./sqlite240 s2k.db <$sqlfile" 1] + set t [expr {[lindex $t 0]/1000000.0}] + puts [format $format {SQLite 2.4 (cache=2000):} $t] + set t [time "exec ./sqlite240 sns.db <$sqlfile" 1] + set t [expr {[lindex $t 0]/1000000.0}] + puts [format $format {SQLite 2.4 (nosync):} $t] + puts "
%s%.3f
" +} + +# Initialize the environment +# +expr srand(1) +catch {exec /bin/sh -c {rm -f s*.db}} +set fd [open clear.sql w] +puts $fd { + drop table t1; + drop table t2; +} +close $fd +catch {exec psql drh =1000} { + set txt "[number_name [expr {$n/1000}]] thousand" + set n [expr {$n%1000}] + } else { + set txt {} + } + if {$n>100} { + append txt " [lindex $::ones [expr {$n/100}]] hundred" + set n [expr {$n%100}] + } + if {$n>19} { + append txt " [lindex $::tens [expr {$n/10}]]" + set n [expr {$n%10}] + } + if {$n>0} { + append txt " [lindex $::ones $n]" + } + set txt [string trim $txt] + if {$txt==""} {set txt zero} + return $txt +} + +# TEST 1 +# +set fd [open test1.sql w] +puts $fd "CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100));" +for {set i 1} {$i<=1000} {incr i} { + set r [expr {int(rand()*100000)}] + puts $fd "INSERT INTO t1 VALUES($i,$r,'[number_name $r]');" +} +close $fd +runtest {1000 INSERTs} test1.sql + +# TEST 2 +# +set fd [open test2.sql w] +puts $fd "BEGIN;" +puts $fd "CREATE TABLE t2(a INTEGER, b INTEGER, c VARCHAR(100));" +for {set i 1} {$i<=25000} {incr i} { + set r [expr {int(rand()*500000)}] + puts $fd "INSERT INTO t2 VALUES($i,$r,'[number_name $r]');" +} +puts $fd "COMMIT;" +close $fd +runtest {25000 INSERTs in a transaction} test2.sql + +# TEST 3 +# +set fd [open test3.sql w] +for {set i 0} {$i<100} {incr i} { + set lwr [expr {$i*100}] + set upr [expr {($i+10)*100}] + puts $fd "SELECT count(*), avg(b) FROM t2 WHERE b>=$lwr AND b<$upr;" +} +close $fd +runtest {100 SELECTs without an index} test3.sql + +# TEST 4 +# +set fd [open test4.sql w] +puts $fd {CREATE INDEX i2a ON t2(a);} +puts $fd {CREATE INDEX i2b ON t2(b);} +close $fd +runtest {Creating an index} test4.sql + +# TEST 5 +# +set fd [open test5.sql w] +for {set i 0} {$i<5000} {incr i} { + set lwr [expr {$i*100}] + set upr [expr {($i+1)*100}] + puts $fd "SELECT count(*), avg(b) FROM t2 WHERE b>=$lwr AND b<$upr;" +} +close $fd +runtest {5000 SELECTs with an index} test5.sql + +# TEST 6 +# +set fd [open test6.sql w] +puts $fd "BEGIN;" +for {set i 0} {$i<100} {incr i} { + set lwr [expr {$i*10}] + set upr [expr {($i+1)*10}] + puts $fd "UPDATE t1 SET b=b*2 WHERE a>=$lwr AND a<$upr;" +} +puts $fd "COMMIT;" +close $fd +runtest {100 UPDATEs without an index} test6.sql + + +# TEST 7 +set fd [open test7.sql w] +puts $fd "BEGIN;" +for {set i 1} {$i<=25000} {incr i} { + puts $fd "UPDATE t2 SET b=b+a WHERE a=$i;" +} +puts $fd "COMMIT;" +close $fd +runtest {25000 UPDATEs with an index} test7.sql + +# TEST 8 +set fd [open test8.sql w] +puts $fd "BEGIN;" +puts $fd "INSERT INTO t1 SELECT * FROM t2;" +puts $fd "INSERT INTO t2 SELECT * FROM t1;" +puts $fd "COMMIT;" +close $fd +runtest {INSERTs from a SELECT} test8.sql + +# TEST 9 +# +set fd [open test9.sql w] +puts $fd {DELETE FROM t2 WHERE c LIKE '%fifty%';} +close $fd +runtest {DELETE without an index} test9.sql + +# TEST 10 +# +set fd [open test10.sql w] +puts $fd {DELETE FROM t2 WHERE a>10 AND a<20000;} +close $fd +runtest {DELETE with an index} test10.sql + +# TEST 11 +# +set fd [open test11.sql w] +puts $fd {INSERT INTO t2 SELECT * FROM t1;} +close $fd +runtest {A big INSERT after a big DELETE} test11.sql + +# TEST 12 +# +set fd [open test12.sql w] +puts $fd {BEGIN;} +puts $fd {DELETE FROM t1;} +for {set i 1} {$i<=1000} {incr i} { + set r [expr {int(rand()*100000)}] + puts $fd "INSERT INTO t1 VALUES($i,$r,'[number_name $r]');" +} +puts $fd {COMMIT;} +close $fd +runtest {A big DELETE followed by many small INSERTs} test12.sql + +# TEST 13 +# +set fd [open test13.sql w] +puts $fd {DROP TABLE t1;} +puts $fd {DROP TABLE t2;} +close $fd +runtest {DROP TABLE} test13.sql diff --git a/www/changes.tcl b/www/changes.tcl index fe8ac42ce6..0397ac1241 100644 --- a/www/changes.tcl +++ b/www/changes.tcl @@ -38,6 +38,8 @@ chng {2002 Mar * (2.4.0)} { impact database integrity, since the pages contain no real data, but it does make large INSERT operations about 2.5 times faster and large DELETEs about 5 times faster. +
  • Made the CACHE_SIZE pragma persistent
  • +
  • Added the SYNCHRONOUS pragma
  • } chng {2002 Feb 18 (2.3.3)} {