diff options
author | drh <drh@noemail.net> | 2004-07-22 01:19:35 +0000 |
---|---|---|
committer | drh <drh@noemail.net> | 2004-07-22 01:19:35 +0000 |
commit | 90f5ecb39de54f08c69594cd239b57ef53519211 (patch) | |
tree | 1e6a04a8dfd624962cbb5a4435ad67cdd2400c89 /src | |
parent | 900dfba8ef6ccaa115a5525df20e4c321b894b4c (diff) | |
download | sqlite-90f5ecb39de54f08c69594cd239b57ef53519211.tar.gz sqlite-90f5ecb39de54f08c69594cd239b57ef53519211.zip |
Initial implementation of variable page sizes and the temp_store pragma. (CVS 1843)
FossilOrigin-Name: 4cf6e9db757931aba2f300b7869305434d6f2d2b
Diffstat (limited to 'src')
-rw-r--r-- | src/attach.c | 20 | ||||
-rw-r--r-- | src/btree.c | 100 | ||||
-rw-r--r-- | src/btree.h | 13 | ||||
-rw-r--r-- | src/build.c | 11 | ||||
-rw-r--r-- | src/main.c | 51 | ||||
-rw-r--r-- | src/pager.c | 111 | ||||
-rw-r--r-- | src/pager.h | 46 | ||||
-rw-r--r-- | src/pragma.c | 148 | ||||
-rw-r--r-- | src/sqliteInt.h | 40 | ||||
-rw-r--r-- | src/test2.c | 24 | ||||
-rw-r--r-- | src/test3.c | 5 |
11 files changed, 370 insertions, 199 deletions
diff --git a/src/attach.c b/src/attach.c index dc8f99c33..1679abf59 100644 --- a/src/attach.c +++ b/src/attach.c @@ -11,7 +11,7 @@ ************************************************************************* ** This file contains code used to implement the ATTACH and DETACH commands. ** -** $Id: attach.c,v 1.22 2004/07/19 00:56:24 drh Exp $ +** $Id: attach.c,v 1.23 2004/07/22 01:19:35 drh Exp $ */ #include "sqliteInt.h" @@ -91,19 +91,15 @@ void sqlite3Attach(Parse *pParse, Token *pFilename, Token *pDbname, Token *pKey) sqlite3ErrorMsg(pParse, "unable to open database: %s", zFile); } #if SQLITE_HAS_CODEC - { - extern int sqliteCodecAttach(sqlite*, int, void*, int); + assert( pKey!=0 ); + if( pKey->n>0 ){ + extern int sqlite3CodecAttach(sqlite*, int, void*, int); char *zKey = 0; int nKey; - if( pKey && pKey->z && pKey->n ){ - sqlite3SetNString(&zKey, pKey->z, pKey->n, 0); - sqlite3Dequote(zKey); - nKey = strlen(zKey); - }else{ - zKey = 0; - nKey = 0; - } - sqliteCodecAttach(db, db->nDb-1, zKey, nKey); + sqlite3BtreeSetPageSize(aNew->pBt, -1, 4); + sqlite3CodecAttach(db, db->nDb-1, zKey, nKey); + zKey = sqlite3NameFromToken(pKey); + nKey = strlen(zKey); } #endif sqliteFree(zFile); diff --git a/src/btree.c b/src/btree.c index 6bfe24cf4..fcee69176 100644 --- a/src/btree.c +++ b/src/btree.c @@ -9,7 +9,7 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* -** $Id: btree.c,v 1.177 2004/07/20 12:45:22 drh Exp $ +** $Id: btree.c,v 1.178 2004/07/22 01:19:35 drh Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** For a detailed discussion of BTrees, refer to @@ -211,27 +211,16 @@ #include <assert.h> -/* Maximum page size. The upper bound on this value is 65536 (a limit -** imposed by the 2-byte size of cell array pointers.) The -** maximum page size determines the amount of stack space allocated -** by many of the routines in this module. On embedded architectures -** or any machine where memory and especially stack memory is limited, -** one may wish to chose a smaller value for the maximum page size. -*/ -#ifndef MX_PAGE_SIZE -# define MX_PAGE_SIZE 1024 -#endif - /* The following value is the maximum cell size assuming a maximum page ** size give above. */ -#define MX_CELL_SIZE (MX_PAGE_SIZE-8) +#define MX_CELL_SIZE (SQLITE_MAX_PAGE_SIZE-8) /* The maximum number of cells on a single page of the database. This ** assumes a minimum cell size of 3 bytes. Such small cells will be ** exceedingly rare, but they are possible. */ -#define MX_CELL ((MX_PAGE_SIZE-8)/3) +#define MX_CELL ((SQLITE_MAX_PAGE_SIZE-8)/3) /* Forward declarations */ typedef struct MemPage MemPage; @@ -308,6 +297,7 @@ struct Btree { u8 maxEmbedFrac; /* Maximum payload as % of total page size */ u8 minEmbedFrac; /* Minimum payload as % of total page size */ u8 minLeafFrac; /* Minimum leaf payload as % of total page size */ + u8 pageSizeFixed; /* True if the page size can no longer be changed */ u16 pageSize; /* Total number of bytes on a page */ u16 usableSize; /* Number of usable bytes on each page */ int maxLocal; /* Maximum local payload in non-LEAFDATA tables */ @@ -532,7 +522,7 @@ static void _pageIntegrity(MemPage *pPage){ int i, j, idx, c, pc, hdr, nFree; int cellOffset; int nCell, cellLimit; - u8 used[MX_PAGE_SIZE]; + u8 used[SQLITE_MAX_PAGE_SIZE]; usableSize = pPage->pBt->usableSize; assert( pPage->aData==&((unsigned char*)pPage)[-pPage->pBt->pageSize] ); @@ -616,11 +606,11 @@ static void defragmentPage(MemPage *pPage){ int brk; /* Offset to the cell content area */ int nCell; /* Number of cells on the page */ unsigned char *data; /* The page data */ - unsigned char temp[MX_PAGE_SIZE]; /* Temp holding area for cell content */ + unsigned char temp[SQLITE_MAX_PAGE_SIZE]; /* Temp area for cell content */ assert( sqlite3pager_iswriteable(pPage->aData) ); assert( pPage->pBt!=0 ); - assert( pPage->pBt->usableSize <= MX_PAGE_SIZE ); + assert( pPage->pBt->usableSize <= SQLITE_MAX_PAGE_SIZE ); assert( pPage->nOverflow==0 ); data = pPage->aData; hdr = pPage->hdrOffset; @@ -857,7 +847,7 @@ static int initPage( while( pc>0 ){ int next, size; if( pc>=usableSize ) return SQLITE_CORRUPT; - if( i++>MX_PAGE_SIZE ) return SQLITE_CORRUPT; + if( i++>SQLITE_MAX_PAGE_SIZE ) return SQLITE_CORRUPT; next = get2byte(&data[pc]); size = get2byte(&data[pc+2]); if( next>0 && next<=pc+size+3 ) return SQLITE_CORRUPT; @@ -998,12 +988,12 @@ static void pageReinit(void *pData, int pageSize){ int sqlite3BtreeOpen( const char *zFilename, /* Name of the file containing the BTree database */ Btree **ppBtree, /* Pointer to new Btree object written here */ - int nCache, /* Number of cache pages */ - int flags, /* Options */ - void *pBusyHandler /* Busy callback info passed to pager layer */ + int flags /* Options */ ){ Btree *pBt; int rc; + int nReserve; + unsigned char zDbHeader[100]; /* ** The following asserts make sure that structures used by the btree are @@ -1023,9 +1013,8 @@ int sqlite3BtreeOpen( *ppBtree = 0; return SQLITE_NOMEM; } - if( nCache<10 ) nCache = 10; - rc = sqlite3pager_open(&pBt->pPager, zFilename, nCache, EXTRA_SIZE, - (flags & BTREE_OMIT_JOURNAL)==0, pBusyHandler); + rc = sqlite3pager_open(&pBt->pPager, zFilename, EXTRA_SIZE, + (flags & BTREE_OMIT_JOURNAL)==0); if( rc!=SQLITE_OK ){ if( pBt->pPager ) sqlite3pager_close(pBt->pPager); sqliteFree(pBt); @@ -1037,12 +1026,23 @@ int sqlite3BtreeOpen( pBt->pCursor = 0; pBt->pPage1 = 0; pBt->readOnly = sqlite3pager_isreadonly(pBt->pPager); - pBt->pageSize = SQLITE_PAGE_SIZE; /* FIX ME - read from header */ - pBt->usableSize = pBt->pageSize; - pBt->maxEmbedFrac = 64; /* FIX ME - read from header */ - pBt->minEmbedFrac = 32; /* FIX ME - read from header */ - pBt->minLeafFrac = 32; /* FIX ME - read from header */ - + sqlite3pager_read_fileheader(pBt->pPager, sizeof(zDbHeader), zDbHeader); + pBt->pageSize = get2byte(&zDbHeader[16]); + if( pBt->pageSize<512 || pBt->pageSize>SQLITE_MAX_PAGE_SIZE ){ + pBt->pageSize = SQLITE_DEFAULT_PAGE_SIZE; + pBt->maxEmbedFrac = 64; /* 25% */ + pBt->minEmbedFrac = 32; /* 12.5% */ + pBt->minLeafFrac = 32; /* 12.5% */ + nReserve = 0; + }else{ + nReserve = zDbHeader[20]; + pBt->maxEmbedFrac = zDbHeader[21]; + pBt->minEmbedFrac = zDbHeader[22]; + pBt->minLeafFrac = zDbHeader[23]; + pBt->pageSizeFixed = 1; + } + pBt->usableSize = pBt->pageSize - nReserve; + sqlite3pager_set_pagesize(pBt->pPager, pBt->pageSize); *ppBtree = pBt; return SQLITE_OK; } @@ -1060,6 +1060,14 @@ int sqlite3BtreeClose(Btree *pBt){ } /* +** Change the busy handler callback function. +*/ +int sqlite3BtreeSetBusyHandler(Btree *pBt, BusyHandler *pHandler){ + sqlite3pager_set_busyhandler(pBt->pPager, pHandler); + return SQLITE_OK; +} + +/* ** Change the limit on the number of pages allowed in the cache. ** ** The maximum number of cache pages is set to the absolute @@ -1093,6 +1101,31 @@ int sqlite3BtreeSetSafetyLevel(Btree *pBt, int level){ } /* +** Change the default pages size and the number of reserved bytes per page. +*/ +int sqlite3BtreeSetPageSize(Btree *pBt, int pageSize, int nReserve){ + if( pBt->pageSizeFixed ){ + return SQLITE_READONLY; + } + if( nReserve<0 ){ + nReserve = pBt->pageSize - pBt->usableSize; + } + if( pageSize>512 && pageSize<SQLITE_MAX_PAGE_SIZE ){ + pBt->pageSize = pageSize; + sqlite3pager_set_pagesize(pBt->pPager, pageSize); + } + pBt->usableSize = pBt->pageSize - nReserve; + return SQLITE_OK; +} + +/* +** Return the currently defined page size +*/ +int sqlite3BtreeGetPageSize(Btree *pBt){ + return pBt->pageSize; +} + +/* ** Get a reference to pPage1 of the database file. This will ** also acquire a readlock on that file. ** @@ -1154,6 +1187,7 @@ static int lockBtree(Btree *pBt){ } assert( pBt->maxLeaf + 23 <= MX_CELL_SIZE ); pBt->pPage1 = pPage1; + pBt->pageSizeFixed = 1; return SQLITE_OK; page1_init_failed: @@ -2863,8 +2897,8 @@ static int balance_nonroot(MemPage *pPage){ int szNew[NB+2]; /* Combined size of cells place on i-th page */ u8 *apCell[(MX_CELL+2)*NB]; /* All cells from pages being balanced */ int szCell[(MX_CELL+2)*NB]; /* Local size of all cells */ - u8 aCopy[NB][MX_PAGE_SIZE+sizeof(MemPage)]; /* Space for apCopy[] */ - u8 aSpace[MX_PAGE_SIZE*5]; /* Space to copies of divider cells */ + u8 aCopy[NB][SQLITE_MAX_PAGE_SIZE+sizeof(MemPage)]; /* Space for apCopy[] */ + u8 aSpace[SQLITE_MAX_PAGE_SIZE*5]; /* Space to copies of divider cells */ /* ** Find the parent page. @@ -4042,7 +4076,7 @@ static int checkTreePage( int maxLocal, usableSize; char zMsg[100]; char zContext[100]; - char hit[MX_PAGE_SIZE]; + char hit[SQLITE_MAX_PAGE_SIZE]; /* Check that the page exists */ diff --git a/src/btree.h b/src/btree.h index 73ee7341a..19261b232 100644 --- a/src/btree.h +++ b/src/btree.h @@ -13,7 +13,7 @@ ** subsystem. See comments in the source code for a detailed description ** of what each interface routine does. ** -** @(#) $Id: btree.h,v 1.55 2004/06/26 08:38:25 danielk1977 Exp $ +** @(#) $Id: btree.h,v 1.56 2004/07/22 01:19:35 drh Exp $ */ #ifndef _BTREE_H_ #define _BTREE_H_ @@ -31,11 +31,9 @@ typedef struct BtCursor BtCursor; int sqlite3BtreeOpen( - const char *zFilename, - Btree **, - int nCache, - int flags, - void *pBusyHandler + const char *zFilename, /* Name of database file to open */ + Btree **, /* Return open Btree* here */ + int flags /* Flags */ ); /* The flags parameter to sqlite3BtreeOpen can be the bitwise or of the @@ -45,8 +43,11 @@ int sqlite3BtreeOpen( #define BTREE_MEMORY 2 /* In-memory DB. No argument */ int sqlite3BtreeClose(Btree*); +int sqlite3BtreeSetBusyHandler(Btree*,BusyHandler*); int sqlite3BtreeSetCacheSize(Btree*,int); int sqlite3BtreeSetSafetyLevel(Btree*,int); +int sqlite3BtreeSetPageSize(Btree*,int,int); +int sqlite3BtreeGetPageSize(Btree*); int sqlite3BtreeBeginTrans(Btree*,int); int sqlite3BtreeCommit(Btree*); int sqlite3BtreeRollback(Btree*); diff --git a/src/build.c b/src/build.c index 2acf30850..7f27985f2 100644 --- a/src/build.c +++ b/src/build.c @@ -23,7 +23,7 @@ ** ROLLBACK ** PRAGMA ** -** $Id: build.c,v 1.239 2004/07/20 12:45:22 drh Exp $ +** $Id: build.c,v 1.240 2004/07/22 01:19:35 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> @@ -447,9 +447,10 @@ void sqlite3OpenMasterTable(Vdbe *v, int iDb){ */ int findDb(sqlite3 *db, Token *pName){ int i; - for(i=0; i<db->nDb; i++){ - if( pName->n==strlen(db->aDb[i].zName) && - 0==sqlite3StrNICmp(db->aDb[i].zName, pName->z, pName->n) ){ + Db *pDb; + for(pDb=db->aDb, i=0; i<db->nDb; i++, pDb++){ + if( pName->n==strlen(pDb->zName) && + 0==sqlite3StrNICmp(pDb->zName, pName->z, pName->n) ){ return i; } } @@ -474,7 +475,7 @@ int findDb(sqlite3 *db, Token *pName){ */ int sqlite3TwoPartName( Parse *pParse, /* Parsing and code generating context */ - Token *pName1, /* The "xxx" in the name "xxx.yyy" */ + Token *pName1, /* The "xxx" in the name "xxx.yyy" or "xxx" */ Token *pName2, /* The "yyy" in the name "xxx.yyy" */ Token **pUnqual /* Write the unqualified object name here */ ){ diff --git a/src/main.c b/src/main.c index 2bf89a774..24a4c19c4 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.245 2004/07/19 17:25:25 drh Exp $ +** $Id: main.c,v 1.246 2004/07/22 01:19:35 drh Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -821,6 +821,22 @@ void *sqlite3_commit_hook( ** the connection is closed.) If zFilename is NULL then the database ** is for temporary use only and is deleted as soon as the connection ** is closed. +** +** A temporary database can be either a disk file (that is automatically +** deleted when the file is closed) or a set of red-black trees held in memory, +** depending on the values of the TEMP_STORE compile-time macro and the +** db->temp_store variable, according to the following chart: +** +** TEMP_STORE db->temp_store Location of temporary database +** ---------- -------------- ------------------------------ +** 0 any file +** 1 1 file +** 1 2 memory +** 1 0 file +** 2 1 file +** 2 2 memory +** 2 0 memory +** 3 any memory */ int sqlite3BtreeFactory( const sqlite *db, /* Main database when opening aux otherwise 0 */ @@ -830,20 +846,41 @@ int sqlite3BtreeFactory( Btree **ppBtree /* Pointer to new Btree object written here */ ){ int btree_flags = 0; + int rc; + int useMem = 0; assert( ppBtree != 0); if( omitJournal ){ btree_flags |= BTREE_OMIT_JOURNAL; } - if( !zFilename || !strcmp(zFilename, ":memory:") ){ - /* If zFilename is NULL or the magic string ":memory:" then the - ** new btree storest data in main memory, not a file. - */ + if( zFilename==0 ){ +#ifndef TEMP_STORE +# define TEMP_STORE 2 +#endif +#if TEMP_STORE==0 + useMem = 0; +#endif +#if TEMP_STORE==1 + useMem = db->temp_store==2; +#endif +#if TEMP_STORE==2 + useMem = db->temp_store!=1; +#endif +#if TEMP_STORE==3 + useMem = 1; +#endif + } + if( (zFilename && strcmp(zFilename, ":memory:")==0) + || (zFilename==0 && useMem) ){ btree_flags |= BTREE_MEMORY; } - return sqlite3BtreeOpen(zFilename, ppBtree, nCache, btree_flags, - (void *)&db->busyHandler); + rc = sqlite3BtreeOpen(zFilename, ppBtree, btree_flags); + if( rc==SQLITE_OK ){ + sqlite3BtreeSetBusyHandler(*ppBtree, (void*)&db->busyHandler); + sqlite3BtreeSetCacheSize(*ppBtree, nCache); + } + return rc; } /* diff --git a/src/pager.c b/src/pager.c index 3f5b9fff6..fc7bce9ed 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.151 2004/07/20 12:45:22 drh Exp $ +** @(#) $Id: pager.c,v 1.152 2004/07/22 01:19:35 drh Exp $ */ #include "os.h" /* Must be first to enable large file support */ #include "sqliteInt.h" @@ -130,7 +130,7 @@ struct PgHdr { u8 alwaysRollback; /* Disable dont_rollback() for this page */ short int nRef; /* Number of users of this page */ PgHdr *pDirty; /* Dirty pages sorted by PgHdr.pgno */ - /* SQLITE_PAGE_SIZE bytes of page data follow this header */ + /* pPager->pageSize bytes of page data follow this header */ /* Pager.nExtra bytes of local data follow the page data */ }; @@ -166,7 +166,7 @@ struct PgHistory { */ #define PGHDR_TO_DATA(P) ((void*)(&(P)[1])) #define DATA_TO_PGHDR(D) (&((PgHdr*)(D))[-1]) -#define PGHDR_TO_EXTRA(P) ((void*)&((char*)(&(P)[1]))[SQLITE_PAGE_SIZE]) +#define PGHDR_TO_EXTRA(G,P) ((void*)&((char*)(&(G)[1]))[(P)->pageSize]) #define PGHDR_TO_HIST(P,PGR) \ ((PgHistory*)&((char*)(&(P)[1]))[(PGR)->pageSize+(PGR)->nExtra]) @@ -262,7 +262,7 @@ struct Pager { ** ** The sanity checking information for the new journal format consists ** of a 32-bit checksum on each page of data. The checksum covers both -** the page number and the SQLITE_PAGE_SIZE bytes of data for the page. +** the page number and the pPager->pageSize bytes of data for the page. ** This cksum is initialized to a 32-bit random value that appears in the ** journal file right after the header. The random initializer is important, ** because garbage data that appears at the end of a journal is likely @@ -832,7 +832,7 @@ static int pager_playback_one_page(Pager *pPager, OsFile *jfd, int useCksum){ PgHdr *pPg; /* An existing page in the cache */ Pgno pgno; /* The page number of a page in journal */ u32 cksum; /* Checksum used for sanity checking */ - u8 aData[SQLITE_PAGE_SIZE]; /* Store data here */ + u8 aData[SQLITE_MAX_PAGE_SIZE]; /* Temp storage for a page */ rc = read32bits(jfd, &pgno); if( rc!=SQLITE_OK ) return rc; @@ -873,8 +873,8 @@ static int pager_playback_one_page(Pager *pPager, OsFile *jfd, int useCksum){ assert( pPager->state>=PAGER_EXCLUSIVE || pPg ); TRACE2("PLAYBACK page %d\n", pgno); if( pPager->state>=PAGER_EXCLUSIVE ){ - sqlite3OsSeek(&pPager->fd, (pgno-1)*(off_t)SQLITE_PAGE_SIZE); - rc = sqlite3OsWrite(&pPager->fd, aData, SQLITE_PAGE_SIZE); + sqlite3OsSeek(&pPager->fd, (pgno-1)*(off_t)pPager->pageSize); + rc = sqlite3OsWrite(&pPager->fd, aData, pPager->pageSize); } if( pPg ){ /* No page should ever be rolled back that is in use, except for page @@ -995,23 +995,23 @@ static int pager_reload_cache(Pager *pPager){ PgHdr *pPg; int rc = SQLITE_OK; for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){ - char zBuf[SQLITE_PAGE_SIZE]; + char zBuf[SQLITE_MAX_PAGE_SIZE]; if( !pPg->dirty ) continue; if( (int)pPg->pgno <= pPager->origDbSize ){ - sqlite3OsSeek(&pPager->fd, SQLITE_PAGE_SIZE*(off_t)(pPg->pgno-1)); - rc = sqlite3OsRead(&pPager->fd, zBuf, SQLITE_PAGE_SIZE); + sqlite3OsSeek(&pPager->fd, pPager->pageSize*(off_t)(pPg->pgno-1)); + rc = sqlite3OsRead(&pPager->fd, zBuf, pPager->pageSize); TRACE2("REFETCH page %d\n", pPg->pgno); CODEC(pPager, zBuf, pPg->pgno, 2); if( rc ) break; }else{ - memset(zBuf, 0, SQLITE_PAGE_SIZE); + memset(zBuf, 0, pPager->pageSize); } - if( pPg->nRef==0 || memcmp(zBuf, PGHDR_TO_DATA(pPg), SQLITE_PAGE_SIZE) ){ - memcpy(PGHDR_TO_DATA(pPg), zBuf, SQLITE_PAGE_SIZE); + if( pPg->nRef==0 || memcmp(zBuf, PGHDR_TO_DATA(pPg), pPager->pageSize) ){ + memcpy(PGHDR_TO_DATA(pPg), zBuf, pPager->pageSize); if( pPager->xReiniter ){ pPager->xReiniter(PGHDR_TO_DATA(pPg), pPager->pageSize); }else{ - memset(PGHDR_TO_EXTRA(pPg), 0, pPager->nExtra); + memset(PGHDR_TO_EXTRA(pPg, pPager), 0, pPager->nExtra); } } pPg->needSync = 0; @@ -1138,7 +1138,7 @@ static int pager_playback(Pager *pPager){ */ if( pPager->journalOff==JOURNAL_HDR_SZ(pPager) ){ assert( pPager->origDbSize==0 || pPager->origDbSize==mxPg ); - rc = sqlite3OsTruncate(&pPager->fd, SQLITE_PAGE_SIZE*(off_t)mxPg); + rc = sqlite3OsTruncate(&pPager->fd, pPager->pageSize*(off_t)mxPg); if( rc!=SQLITE_OK ){ goto end_playback; } @@ -1238,7 +1238,7 @@ static int pager_stmt_playback(Pager *pPager){ /* Truncate the database back to its original size. */ - rc = sqlite3OsTruncate(&pPager->fd, SQLITE_PAGE_SIZE*(off_t)pPager->stmtSize); + rc = sqlite3OsTruncate(&pPager->fd, pPager->pageSize*(off_t)pPager->stmtSize); pPager->dbSize = pPager->stmtSize; /* Figure out how many records are in the statement journal. @@ -1396,14 +1396,16 @@ static int sqlite3pager_opentemp(char *zFile, OsFile *fd){ ** If zFilename is NULL then a randomly-named temporary file is created ** and used as the file to be cached. The file will be deleted ** automatically when it is closed. +** +** If zFilename is ":memory:" then all information is held in cache. +** It is never written to disk. This can be used to implement an +** in-memory database. */ int sqlite3pager_open( Pager **ppPager, /* Return the Pager structure here */ const char *zFilename, /* Name of the database file to open */ - int mxPage, /* Max number of in-memory cache pages */ int nExtra, /* Extra bytes append to each in-memory page */ - int useJournal, /* TRUE to use a rollback journal on this file */ - void *pBusyHandler /* Busy callback */ + int useJournal /* TRUE to use a rollback journal on this file */ ){ Pager *pPager; char *zFullPathname = 0; @@ -1477,11 +1479,11 @@ int sqlite3pager_open( pPager->stmtInUse = 0; pPager->nRef = 0; pPager->dbSize = memDb-1; - pPager->pageSize = SQLITE_PAGE_SIZE; + pPager->pageSize = SQLITE_DEFAULT_PAGE_SIZE; pPager->stmtSize = 0; pPager->stmtJSize = 0; pPager->nPage = 0; - pPager->mxPage = mxPage>5 ? mxPage : 10; + pPager->mxPage = 100; pPager->state = PAGER_UNLOCK; pPager->errMask = 0; pPager->tempFile = tempFile; @@ -1495,13 +1497,20 @@ int sqlite3pager_open( pPager->pLast = 0; pPager->nExtra = nExtra; pPager->sectorSize = PAGER_SECTOR_SIZE; - pPager->pBusyHandler = (BusyHandler *)pBusyHandler; + pPager->pBusyHandler = 0; memset(pPager->aHash, 0, sizeof(pPager->aHash)); *ppPager = pPager; return SQLITE_OK; } /* +** Set the busy handler function. +*/ +void sqlite3pager_set_busyhandler(Pager *pPager, BusyHandler *pBusyHandler){ + pPager->pBusyHandler = pBusyHandler; +} + +/* ** Set the destructor for this pager. If not NULL, the destructor is called ** when the reference count on each page reaches zero. The destructor can ** be used to clean up information in the extra segment appended to each page. @@ -1525,6 +1534,28 @@ void sqlite3pager_set_reiniter(Pager *pPager, void (*xReinit)(void*,int)){ } /* +** Set the page size. +** +** The page size must only be changed when the cache is empty. +*/ +void sqlite3pager_set_pagesize(Pager *pPager, int pageSize){ + assert( pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE ); + pPager->pageSize = pageSize; +} + +/* +** Read the first N bytes from the beginning of the file into memory +** that pDest points to. No error checking is done. +*/ +void sqlite3pager_read_fileheader(Pager *pPager, int N, unsigned char *pDest){ + memset(pDest, 0, N); + if( pPager->memDb==0 ){ + sqlite3OsSeek(&pPager->fd, 0); + sqlite3OsRead(&pPager->fd, pDest, N); + } +} + +/* ** Return the total number of pages in the disk file associated with ** pPager. */ @@ -1538,8 +1569,8 @@ int sqlite3pager_pagecount(Pager *pPager){ pPager->errMask |= PAGER_ERR_DISK; return 0; } - n /= SQLITE_PAGE_SIZE; - if( !pPager->memDb && n==PENDING_BYTE/SQLITE_PAGE_SIZE ){ + n /= pPager->pageSize; + if( !pPager->memDb && n==PENDING_BYTE/pPager->pageSize ){ n++; } if( pPager->state!=PAGER_UNLOCK ){ @@ -1647,7 +1678,7 @@ int sqlite3pager_truncate(Pager *pPager, Pgno nPage){ if( rc!=SQLITE_OK ){ return rc; } - rc = sqlite3OsTruncate(&pPager->fd, SQLITE_PAGE_SIZE*(off_t)nPage); + rc = sqlite3OsTruncate(&pPager->fd, pPager->pageSize*(off_t)nPage); if( rc==SQLITE_OK ){ pPager->dbSize = nPage; } @@ -1914,10 +1945,10 @@ static int pager_write_pagelist(PgHdr *pList){ while( pList ){ assert( pList->dirty ); - sqlite3OsSeek(&pPager->fd, (pList->pgno-1)*(off_t)SQLITE_PAGE_SIZE); + sqlite3OsSeek(&pPager->fd, (pList->pgno-1)*(off_t)pPager->pageSize); CODEC(pPager, PGHDR_TO_DATA(pList), pList->pgno, 6); TRACE2("STORE page %d\n", pList->pgno); - rc = sqlite3OsWrite(&pPager->fd, PGHDR_TO_DATA(pList), SQLITE_PAGE_SIZE); + rc = sqlite3OsWrite(&pPager->fd, PGHDR_TO_DATA(pList), pPager->pageSize); CODEC(pPager, PGHDR_TO_DATA(pList), pList->pgno, 0); if( rc ) return rc; pList->dirty = 0; @@ -2066,7 +2097,7 @@ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){ pPager->nMiss++; if( pPager->nPage<pPager->mxPage || pPager->pFirst==0 || pPager->memDb ){ /* Create a new page */ - pPg = sqliteMallocRaw( sizeof(*pPg) + SQLITE_PAGE_SIZE + pPg = sqliteMallocRaw( sizeof(*pPg) + pPager->pageSize + sizeof(u32) + pPager->nExtra + pPager->memDb*sizeof(PgHistory) ); if( pPg==0 ){ @@ -2178,7 +2209,7 @@ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){ pPg->pNextHash->pPrevHash = pPg; } if( pPager->nExtra>0 ){ - memset(PGHDR_TO_EXTRA(pPg), 0, pPager->nExtra); + memset(PGHDR_TO_EXTRA(pPg, pPager), 0, pPager->nExtra); } if( pPager->dbSize<0 ) sqlite3pager_pagecount(pPager); if( pPager->errMask!=0 ){ @@ -2187,22 +2218,22 @@ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){ return rc; } if( pPager->dbSize<(int)pgno ){ - memset(PGHDR_TO_DATA(pPg), 0, SQLITE_PAGE_SIZE); + memset(PGHDR_TO_DATA(pPg), 0, pPager->pageSize); }else{ int rc; assert( pPager->memDb==0 ); - sqlite3OsSeek(&pPager->fd, (pgno-1)*(off_t)SQLITE_PAGE_SIZE); - rc = sqlite3OsRead(&pPager->fd, PGHDR_TO_DATA(pPg), SQLITE_PAGE_SIZE); + sqlite3OsSeek(&pPager->fd, (pgno-1)*(off_t)pPager->pageSize); + rc = sqlite3OsRead(&pPager->fd, PGHDR_TO_DATA(pPg), pPager->pageSize); TRACE2("FETCH page %d\n", pPg->pgno); CODEC(pPager, PGHDR_TO_DATA(pPg), pPg->pgno, 3); if( rc!=SQLITE_OK ){ off_t fileSize; if( sqlite3OsFileSize(&pPager->fd,&fileSize)!=SQLITE_OK - || fileSize>=pgno*SQLITE_PAGE_SIZE ){ + || fileSize>=pgno*pPager->pageSize ){ sqlite3pager_unref(PGHDR_TO_DATA(pPg)); return rc; }else{ - memset(PGHDR_TO_DATA(pPg), 0, SQLITE_PAGE_SIZE); + memset(PGHDR_TO_DATA(pPg), 0, pPager->pageSize); } } } @@ -2486,16 +2517,16 @@ int sqlite3pager_write(void *pData){ pPg->inJournal = 1; }else{ u32 cksum = pager_cksum(pPager, pPg->pgno, pData); - saved = *(u32*)PGHDR_TO_EXTRA(pPg); - store32bits(cksum, pPg, SQLITE_PAGE_SIZE); - szPg = SQLITE_PAGE_SIZE+8; + saved = *(u32*)PGHDR_TO_EXTRA(pPg, pPager); + store32bits(cksum, pPg, pPager->pageSize); + szPg = pPager->pageSize+8; store32bits(pPg->pgno, pPg, -4); CODEC(pPager, pData, pPg->pgno, 7); rc = sqlite3OsWrite(&pPager->jfd, &((char*)pData)[-4], szPg); pPager->journalOff += szPg; TRACE3("JOURNAL page %d needSync=%d\n", pPg->pgno, pPg->needSync); CODEC(pPager, pData, pPg->pgno, 0); - *(u32*)PGHDR_TO_EXTRA(pPg) = saved; + *(u32*)PGHDR_TO_EXTRA(pPg, pPager) = saved; if( rc!=SQLITE_OK ){ sqlite3pager_rollback(pPager); pPager->errMask |= PAGER_ERR_FULL; @@ -2538,7 +2569,7 @@ int sqlite3pager_write(void *pData){ }else{ store32bits(pPg->pgno, pPg, -4); CODEC(pPager, pData, pPg->pgno, 7); - rc = sqlite3OsWrite(&pPager->stfd, ((char*)pData)-4, SQLITE_PAGE_SIZE+4); + rc = sqlite3OsWrite(&pPager->stfd, ((char*)pData)-4, pPager->pageSize+4); TRACE2("STMT-JOURNAL page %d\n", pPg->pgno); CODEC(pPager, pData, pPg->pgno, 0); if( rc!=SQLITE_OK ){ @@ -2586,7 +2617,7 @@ int sqlite3pager_overwrite(Pager *pPager, Pgno pgno, void *pData){ if( rc==SQLITE_OK ){ rc = sqlite3pager_write(pPage); if( rc==SQLITE_OK ){ - memcpy(pPage, pData, SQLITE_PAGE_SIZE); + memcpy(pPage, pData, pPager->pageSize); } sqlite3pager_unref(pPage); } diff --git a/src/pager.h b/src/pager.h index d0d195355..cb4a772c5 100644 --- a/src/pager.h +++ b/src/pager.h @@ -13,43 +13,28 @@ ** subsystem. The page cache subsystem reads and writes a file a page ** at a time and provides a journal for rollback. ** -** @(#) $Id: pager.h,v 1.36 2004/06/30 08:20:16 danielk1977 Exp $ +** @(#) $Id: pager.h,v 1.37 2004/07/22 01:19:35 drh Exp $ */ /* -** The size of a page. -** -** You can change this value to another (reasonable) value you want. -** It need not be a power of two, though the interface to the disk -** will likely be faster if it is. -** -** Experiments show that a page size of 1024 gives the best speed -** for common usages. The speed differences for different sizes -** such as 512, 2048, 4096, an so forth, is minimal. Note, however, -** that changing the page size results in a completely imcompatible -** file format. +** The default size of a database page. */ -#ifndef SQLITE_PAGE_SIZE -#define SQLITE_PAGE_SIZE 1024 +#ifndef SQLITE_DEFAULT_PAGE_SIZE +# define SQLITE_DEFAULT_PAGE_SIZE 1024 #endif -/* -** Number of extra bytes of data allocated at the end of each page and -** stored on disk but not used by the higher level btree layer. Changing -** this value results in a completely incompatible file format. +/* Maximum page size. The upper bound on this value is 65536 (a limit +** imposed by the 2-byte size of cell array pointers.) The +** maximum page size determines the amount of stack space allocated +** by many of the routines in pager.c and btree.c On embedded architectures +** or any machine where memory and especially stack memory is limited, +** one may wish to chose a smaller value for the maximum page size. */ -#ifndef SQLITE_PAGE_RESERVE -#define SQLITE_PAGE_RESERVE 0 +#ifndef SQLITE_MAX_PAGE_SIZE +# define SQLITE_MAX_PAGE_SIZE 8192 #endif /* -** The total number of usable bytes stored on disk for each page. -** The usable bytes come at the beginning of the page and the reserve -** bytes come at the end. -*/ -#define SQLITE_USABLE_SIZE (SQLITE_PAGE_SIZE-SQLITE_PAGE_RESERVE) - -/* ** Maximum number of pages in one database. */ #define SQLITE_MAX_PAGE 1073741823 @@ -65,15 +50,18 @@ typedef unsigned int Pgno; */ typedef struct Pager Pager; + /* ** See source code comments for a detailed description of the following ** routines: */ int sqlite3pager_open(Pager **ppPager, const char *zFilename, - int nPage, int nExtra, int useJournal, - void *pBusyHandler); + int nExtra, int useJournal); +void sqlite3pager_set_busyhandler(Pager*, BusyHandler *pBusyHandler); void sqlite3pager_set_destructor(Pager*, void(*)(void*,int)); void sqlite3pager_set_reiniter(Pager*, void(*)(void*,int)); +void sqlite3pager_set_pagesize(Pager*, int); +void sqlite3pager_read_fileheader(Pager*, int, unsigned char*); void sqlite3pager_set_cachesize(Pager*, int); int sqlite3pager_close(Pager *pPager); int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage); diff --git a/src/pragma.c b/src/pragma.c index 411672a41..5c865f5f6 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -11,7 +11,7 @@ ************************************************************************* ** This file contains code used to implement the PRAGMA command. ** -** $Id: pragma.c,v 1.57 2004/06/30 09:49:24 danielk1977 Exp $ +** $Id: pragma.c,v 1.58 2004/07/22 01:19:35 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> @@ -72,6 +72,56 @@ static int getSafetyLevel(char *z){ } /* +** Interpret the given string as a temp db location. Return 1 for file +** backed temporary databases, 2 for the Red-Black tree in memory database +** and 0 to use the compile-time default. +*/ +static int getTempStore(const char *z){ + if( z[0]>='0' && z[0]<='2' ){ + return z[0] - '0'; + }else if( sqlite3StrICmp(z, "file")==0 ){ + return 1; + }else if( sqlite3StrICmp(z, "memory")==0 ){ + return 2; + }else{ + return 0; + } +} + +/* +** If the TEMP database is open, close it and mark the database schema +** as needing reloading. This must be done when using the TEMP_STORE +** or DEFAULT_TEMP_STORE pragmas. +*/ +static int changeTempStorage(Parse *pParse, const char *zStorageType){ + int ts = getTempStore(zStorageType); + sqlite *db = pParse->db; + if( db->temp_store==ts ) return SQLITE_OK; + if( db->aDb[1].pBt!=0 ){ + if( db->flags & SQLITE_InTrans ){ + sqlite3ErrorMsg(pParse, "temporary storage cannot be changed " + "from within a transaction"); + return SQLITE_ERROR; + } + sqlite3BtreeClose(db->aDb[1].pBt); + db->aDb[1].pBt = 0; + sqlite3ResetInternalSchema(db, 0); + } + db->temp_store = ts; + return SQLITE_OK; +} + +/* +** Generate code to return a single integer value. +*/ +static void returnSingleInt(Vdbe *v, const char *zLabel, int value){ + sqlite3VdbeAddOp(v, OP_Integer, value, 0); + sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, zLabel, P3_STATIC); + sqlite3VdbeAddOp(v, OP_Callback, 1, 0); +} + +/* ** Check to see if zRight and zLeft refer to a pragma that queries ** or changes one of the flags in db->flags. Return 1 if so and 0 if not. ** Also, implement the pragma. @@ -99,10 +149,7 @@ static int flagPragma(Parse *pParse, const char *zLeft, const char *zRight){ if( zRight==0 ){ v = sqlite3GetVdbe(pParse); if( v ){ - sqlite3VdbeSetNumCols(v, 1); - sqlite3VdbeSetColName(v, 0, aPragma[i].zName, P3_STATIC); - sqlite3VdbeAddOp(v, OP_Integer, (db->flags & aPragma[i].mask)!=0, 0); - sqlite3VdbeAddOp(v, OP_Callback, 1, 0); + returnSingleInt(v, aPragma[i].zName, (db->flags&aPragma[i].mask)!=0); } }else if( getBoolean(zRight) ){ db->flags |= aPragma[i].mask; @@ -125,6 +172,10 @@ static int flagPragma(Parse *pParse, const char *zLeft, const char *zRight){ ** The identifier might also be a string. The value is a string, and ** identifier, or a number. If minusFlag is true, then the value is ** a number that was preceded by a minus sign. +** +** If the left side is "database.id" then pId1 is the database name +** and pId2 is the id. If the left side is just "id" then pId1 is the +** id and pId2 is any empty string. */ void sqlite3Pragma( Parse *pParse, @@ -139,6 +190,7 @@ void sqlite3Pragma( Token *pId; /* Pointer to <id> token */ int iDb; /* Database index for <database> */ sqlite *db = pParse->db; + Db *pDb; Vdbe *v = sqlite3GetVdbe(pParse); if( v==0 ) return; @@ -146,6 +198,7 @@ void sqlite3Pragma( ** index of the database this pragma is being applied to in db.aDb[]. */ iDb = sqlite3TwoPartName(pParse, pId1, pId2, &pId); if( iDb<0 ) return; + pDb = &db->aDb[iDb]; zLeft = sqlite3NameFromToken(pId); if( !zLeft ) return; @@ -156,14 +209,14 @@ void sqlite3Pragma( zRight = sqlite3NameFromToken(pValue); } - zDb = ((iDb>0)?db->aDb[iDb].zName:0); + zDb = ((iDb>0)?pDb->zName:0); if( sqlite3AuthCheck(pParse, SQLITE_PRAGMA, zLeft, zRight, zDb) ){ goto pragma_out; } /* - ** PRAGMA default_cache_size - ** PRAGMA default_cache_size=N + ** PRAGMA [database.]default_cache_size + ** PRAGMA [database.]default_cache_size=N ** ** The first form reports the current persistent setting for the ** page cache size. The value returned is the maximum number of @@ -206,14 +259,33 @@ void sqlite3Pragma( sqlite3VdbeAddOp(v, OP_Negative, 0, 0); sqlite3VdbeAddOp(v, OP_SetCookie, iDb, 2); sqlite3EndWriteOperation(pParse); - db->aDb[iDb].cache_size = size; - sqlite3BtreeSetCacheSize(db->aDb[iDb].pBt, db->aDb[iDb].cache_size); + pDb->cache_size = size; + sqlite3BtreeSetCacheSize(pDb->pBt, pDb->cache_size); + } + }else + + /* + ** PRAGMA [database.]page_size + ** PRAGMA [database.]page_size=N + ** + ** The first form reports the current setting for the + ** database page size in bytes. The second form sets the + ** database page size value. The value can only be set if + ** the database has not yet been created. + */ + if( sqlite3StrICmp(zLeft,"page_size")==0 ){ + Btree *pBt = pDb->pBt; + if( !zRight ){ + int size = pBt ? sqlite3BtreeGetPageSize(pBt) : 0; + returnSingleInt(v, "page_size", size); + }else{ + sqlite3BtreeSetPageSize(pBt, atoi(zRight), 0); } }else /* - ** PRAGMA cache_size - ** PRAGMA cache_size=N + ** PRAGMA [database.]cache_size + ** PRAGMA [database.]cache_size=N ** ** The first form reports the current local setting for the ** page cache size. The local setting can be different from @@ -226,28 +298,39 @@ void sqlite3Pragma( ** N should be a positive integer. */ if( sqlite3StrICmp(zLeft,"cache_size")==0 ){ - static VdbeOpList getCacheSize[] = { - { OP_Callback, 1, 0, 0}, - }; if( sqlite3ReadSchema(pParse) ) goto pragma_out; if( !zRight ){ - int size = db->aDb[iDb].cache_size; - assert( size>0 ); - sqlite3VdbeAddOp(v, OP_Integer, size, 0); - sqlite3VdbeSetNumCols(v, 1); - sqlite3VdbeSetColName(v, 0, "cache_size", P3_STATIC); - sqlite3VdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize); + returnSingleInt(v, "cache_size", pDb->cache_size); }else{ int size = atoi(zRight); if( size<0 ) size = -size; - db->aDb[iDb].cache_size = size; - sqlite3BtreeSetCacheSize(db->aDb[iDb].pBt, db->aDb[iDb].cache_size); + pDb->cache_size = size; + sqlite3BtreeSetCacheSize(pDb->pBt, pDb->cache_size); + } + }else + + /* + ** PRAGMA temp_store + ** PRAGMA temp_store = "default"|"memory"|"file" + ** + ** Return or set the local value of the temp_store flag. Changing + ** the local value does not make changes to the disk file and the default + ** value will be restored the next time the database is opened. + ** + ** Note that it is possible for the library compile-time options to + ** override this setting + */ + if( sqlite3StrICmp(zLeft, "temp_store")==0 ){ + if( !zRight ){ + returnSingleInt(v, "temp_store", db->temp_store); + }else{ + changeTempStorage(pParse, zRight); } }else /* - ** PRAGMA synchronous - ** PRAGMA synchronous=OFF|ON|NORMAL|FULL + ** PRAGMA [database.]synchronous + ** PRAGMA [database.]synchronous=OFF|ON|NORMAL|FULL ** ** Return or set the local value of the synchronous flag. Changing ** the local value does not make changes to the disk file and the @@ -255,22 +338,16 @@ void sqlite3Pragma( ** opened. */ if( sqlite3StrICmp(zLeft,"synchronous")==0 ){ - static VdbeOpList getSync[] = { - { OP_Callback, 1, 0, 0}, - }; if( sqlite3ReadSchema(pParse) ) goto pragma_out; if( !zRight ){ - sqlite3VdbeSetNumCols(v, 1); - sqlite3VdbeSetColName(v, 0, "synchronous", P3_STATIC); - sqlite3VdbeAddOp(v, OP_Integer, db->aDb[iDb].safety_level-1, 0); - sqlite3VdbeAddOpList(v, ArraySize(getSync), getSync); + returnSingleInt(v, "synchronous", pDb->safety_level-1); }else{ if( !db->autoCommit ){ sqlite3ErrorMsg(pParse, "Safety level may not be changed inside a transaction"); }else{ - db->aDb[iDb].safety_level = getSafetyLevel(zRight)+1; - sqlite3BtreeSetSafetyLevel(db->aDb[iDb].pBt,db->aDb[iDb].safety_level); + pDb->safety_level = getSafetyLevel(zRight)+1; + sqlite3BtreeSetSafetyLevel(pDb->pBt, pDb->safety_level); } } }else @@ -286,7 +363,8 @@ void sqlite3Pragma( #endif if( flagPragma(pParse, zLeft, zRight) ){ - /* The flagPragma() call also generates any necessary code */ + /* The flagPragma() subroutine also generates any necessary code + ** there is nothing more to do here */ }else /* diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 629664827..1db96f2b7 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.306 2004/07/20 12:45:22 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.307 2004/07/22 01:19:35 drh Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ @@ -139,7 +139,23 @@ extern const int sqlite3one; typedef struct sqlite sqlite; /* -** Defer sourcing vdbe.h until after the "u8" typedef is defined. +** An instance of the following structure is used to store the busy-handler +** callback for a given sqlite handle. +** +** The sqlite.busyHandler member of the sqlite struct contains the busy +** callback for the database handle. Each pager opened via the sqlite +** handle is passed a pointer to sqlite.busyHandler. The busy-handler +** callback is currently invoked only from within pager.c. +*/ +typedef struct BusyHandler BusyHandler; +struct BusyHandler { + int (*xFunc)(void *,int); /* The busy callback */ + void *pArg; /* First arg to busy callback */ +}; + +/* +** Defer sourcing vdbe.h and btree.h until after the "u8" and +** "BusyHandler typedefs. */ #include "vdbe.h" #include "btree.h" @@ -262,7 +278,6 @@ typedef struct AuthContext AuthContext; typedef struct KeyClass KeyClass; typedef struct CollSeq CollSeq; typedef struct KeyInfo KeyInfo; -typedef struct BusyHandler BusyHandler; /* ** Each database file to be accessed by the system is an instance @@ -279,8 +294,8 @@ struct Db { Hash idxHash; /* All (named) indices indexed by name */ Hash trigHash; /* All triggers indexed by name */ Hash aFKey; /* Foreign keys indexed by to-table */ - u8 inTrans; /* 0: not writable. 1: Transaction. 2: Checkpoint */ u16 flags; /* Flags associated with this database */ + u8 inTrans; /* 0: not writable. 1: Transaction. 2: Checkpoint */ u8 safety_level; /* How aggressive at synching data to disk */ int cache_size; /* Number of pages to use in the cache */ void *pAux; /* Auxiliary data. Usually NULL */ @@ -312,20 +327,6 @@ struct Db { #define SQLITE_UTF16NATIVE (SQLITE_BIGENDIAN?SQLITE_UTF16BE:SQLITE_UTF16LE) /* -** An instance of the following structure is used to store the busy-handler -** callback for a given sqlite handle. -** -** The sqlite.busyHandler member of the sqlite struct contains the busy -** callback for the database handle. Each pager opened via the sqlite -** handle is passed a pointer to sqlite.busyHandler. The busy-handler -** callback is currently invoked only from within pager.c. -*/ -struct BusyHandler { - int (*xFunc)(void *,int); /* The busy callback */ - void *pArg; /* First arg to busy callback */ -}; - -/* ** Each database is an instance of the following structure. ** ** The sqlite.lastRowid records the last insert rowid generated by an @@ -357,6 +358,7 @@ struct sqlite { Db aDbStatic[2]; /* Static space for the 2 default backends */ int flags; /* Miscellanous flags. See below */ u8 file_format; /* What file format version is this database? */ + u8 temp_store; /* 1: file 2: memory 0: default */ int nTable; /* Number of tables in the database */ BusyHandler busyHandler; /* Busy callback */ void *pCommitArg; /* Argument to xCommitCallback() */ @@ -1331,7 +1333,7 @@ void sqlite3DeferForeignKey(Parse*, int); void sqlite3Attach(Parse*, Token*, Token*, Token*); void sqlite3Detach(Parse*, Token*); int sqlite3BtreeFactory(const sqlite *db, const char *zFilename, - int mode, int nPg, Btree **ppBtree); + int omitJournal, int nCache, Btree **ppBtree); int sqlite3FixInit(DbFixer*, Parse*, int, const char*, const Token*); int sqlite3FixSrcList(DbFixer*, SrcList*); int sqlite3FixSelect(DbFixer*, Select*); diff --git a/src/test2.c b/src/test2.c index 074dc4796..4b98925a9 100644 --- a/src/test2.c +++ b/src/test2.c @@ -13,7 +13,7 @@ ** is not included in the SQLite library. It is used for automated ** testing of the SQLite library. ** -** $Id: test2.c,v 1.23 2004/06/21 18:14:47 drh Exp $ +** $Id: test2.c,v 1.24 2004/07/22 01:19:35 drh Exp $ */ #include "os.h" #include "sqliteInt.h" @@ -56,6 +56,11 @@ static char *errorName(int rc){ } /* +** Page size and reserved size used for testing. +*/ +static int test_pagesize = 1024; + +/* ** Usage: pager_open FILENAME N-PAGE ** ** Open a new pager @@ -76,11 +81,13 @@ static int pager_open( return TCL_ERROR; } if( Tcl_GetInt(interp, argv[2], &nPage) ) return TCL_ERROR; - rc = sqlite3pager_open(&pPager, argv[1], nPage, 0, 1, 0); + rc = sqlite3pager_open(&pPager, argv[1], 0, 1); if( rc!=SQLITE_OK ){ Tcl_AppendResult(interp, errorName(rc), 0); return TCL_ERROR; } + sqlite3pager_set_cachesize(pPager, nPage); + sqlite3pager_set_pagesize(pPager, test_pagesize); sprintf(zBuf,"0x%x",(int)pPager); Tcl_AppendResult(interp, zBuf, 0); return TCL_OK; @@ -468,8 +475,8 @@ static int page_write( Tcl_AppendResult(interp, errorName(rc), 0); return TCL_ERROR; } - strncpy((char*)pPage, argv[2], SQLITE_USABLE_SIZE-1); - ((char*)pPage)[SQLITE_USABLE_SIZE-1] = 0; + strncpy((char*)pPage, argv[2], test_pagesize-1); + ((char*)pPage)[test_pagesize-1] = 0; return TCL_OK; } @@ -526,7 +533,6 @@ static int fake_big_file( */ int Sqlitetest2_Init(Tcl_Interp *interp){ extern int sqlite3_io_error_pending; - char zBuf[100]; static struct { char *zName; Tcl_CmdProc *xProc; @@ -554,11 +560,7 @@ int Sqlitetest2_Init(Tcl_Interp *interp){ } Tcl_LinkVar(interp, "sqlite_io_error_pending", (char*)&sqlite3_io_error_pending, TCL_LINK_INT); - sprintf(zBuf, "%d", SQLITE_PAGE_SIZE); - Tcl_SetVar(interp, "SQLITE_PAGE_SIZE", zBuf, TCL_GLOBAL_ONLY); - sprintf(zBuf, "%d", SQLITE_PAGE_RESERVE); - Tcl_SetVar(interp, "SQLITE_PAGE_RESERVE", zBuf, TCL_GLOBAL_ONLY); - sprintf(zBuf, "%d", SQLITE_USABLE_SIZE); - Tcl_SetVar(interp, "SQLITE_USABLE_SIZE", zBuf, TCL_GLOBAL_ONLY); + Tcl_LinkVar(interp, "pager_pagesize", + (char*)&test_pagesize, TCL_LINK_INT); return TCL_OK; } diff --git a/src/test3.c b/src/test3.c index 70a4617f2..9904f36e7 100644 --- a/src/test3.c +++ b/src/test3.c @@ -13,7 +13,7 @@ ** is not included in the SQLite library. It is used for automated ** testing of the SQLite library. ** -** $Id: test3.c,v 1.48 2004/06/30 04:02:12 drh Exp $ +** $Id: test3.c,v 1.49 2004/07/22 01:19:35 drh Exp $ */ #include "sqliteInt.h" #include "pager.h" @@ -70,11 +70,12 @@ static int btree_open( } if( Tcl_GetInt(interp, argv[2], &nCache) ) return TCL_ERROR; if( Tcl_GetInt(interp, argv[3], &flags) ) return TCL_ERROR; - rc = sqlite3BtreeOpen(argv[1], &pBt, nCache, flags, 0); + rc = sqlite3BtreeOpen(argv[1], &pBt, flags); if( rc!=SQLITE_OK ){ Tcl_AppendResult(interp, errorName(rc), 0); return TCL_ERROR; } + sqlite3BtreeSetCacheSize(pBt, nCache); sprintf(zBuf,"%p", pBt); if( strncmp(zBuf,"0x",2) ){ sprintf(zBuf, "0x%p", pBt); |