aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordrh <drh@noemail.net>2004-07-22 01:19:35 +0000
committerdrh <drh@noemail.net>2004-07-22 01:19:35 +0000
commit90f5ecb39de54f08c69594cd239b57ef53519211 (patch)
tree1e6a04a8dfd624962cbb5a4435ad67cdd2400c89 /src
parent900dfba8ef6ccaa115a5525df20e4c321b894b4c (diff)
downloadsqlite-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.c20
-rw-r--r--src/btree.c100
-rw-r--r--src/btree.h13
-rw-r--r--src/build.c11
-rw-r--r--src/main.c51
-rw-r--r--src/pager.c111
-rw-r--r--src/pager.h46
-rw-r--r--src/pragma.c148
-rw-r--r--src/sqliteInt.h40
-rw-r--r--src/test2.c24
-rw-r--r--src/test3.c5
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);