1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-07 02:42:48 +03:00

Add the ability to turn of calls to fsync() using the "synchronous" pragma.

Increased the default cache size from 100 to 2000 and made the "cache_size"
pragma persistent. (CVS 418)

FossilOrigin-Name: 414da4af1f4aebc3936ca339fbc7932add081912
This commit is contained in:
drh
2002-03-05 01:11:12 +00:00
parent ef2daf547d
commit 603240cf5d
11 changed files with 395 additions and 63 deletions

View File

@@ -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

View File

@@ -1 +1 @@
36a8fe0ad0ee2a67afafc04125dcc085ec1b5a13
414da4af1f4aebc3936ca339fbc7932add081912

View File

@@ -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 <ctype.h>
@@ -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 ){

View File

@@ -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},
};

View File

@@ -43,6 +43,20 @@
# include <winbase.h>
#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( wrote<amt ) return SQLITE_FULL;
return SQLITE_OK;
@@ -517,6 +533,7 @@ int sqliteOsWrite(OsFile *id, const void *pBuf, int amt){
** Move the read/write pointer in a file.
*/
int sqliteOsSeek(OsFile *id, int offset){
SEEK(offset/1024 + 1);
#if OS_UNIX
lseek(id->fd, 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

View File

@@ -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 && 0<cnt-- && pPg->pNextFree ){
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;

View File

@@ -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;}

View File

@@ -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

View File

@@ -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 <ctype.h>
@@ -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->p2<SQLITE_N_BTREE_META );
VERIFY( if( p->tos<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;
}

228
tool/speedtest.tcl Normal file
View File

@@ -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 "<h2>Test $cnt: $title</h2>"
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]<br>\n}
append sql "<i>... [expr {$n-6}] lines omitted</i><br>\n"
for {set i [expr {$n-3}]} {$i<$n} {incr i} {
append sql [lindex $sx $i]<br>\n
}
} else {
regsub -all \n [string trim $sql] <br> sql
}
puts "<blockquote>"
puts "$sql"
puts "</blockquote><table border=0 cellpadding=0 cellspacing=5>"
set format {<tr><td>%s</td><td align="right">%.3f</td></tr>}
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 "</table>"
}
# 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 <clear.sql}
catch {exec mysql drh <clear.sql}
set fd [open 2kinit.sql w]
puts $fd {PRAGMA cache_size=2000; PRAGMA synchronous=on;}
close $fd
exec ./sqlite240 s2k.db <2kinit.sql
set fd [open nosync-init.sql w]
puts $fd {PRAGMA cache_size=2000; PRAGMA synchronous=off;}
close $fd
exec ./sqlite240 sns.db <nosync-init.sql
set ones {zero one two three four five six seven eight nine
ten eleven twelve thirteen fourteen fifteen sixteen seventeen
eighteen nineteen}
set tens {{} ten twenty thirty forty fifty sixty seventy eighty ninety}
proc number_name {n} {
if {$n>=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

View File

@@ -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.</li>
<li>Made the CACHE_SIZE pragma persistent</li>
<li>Added the SYNCHRONOUS pragma</li>
}
chng {2002 Feb 18 (2.3.3)} {