Initial implementation of variable page sizes and the temp_store pragma. (CVS 1843)

FossilOrigin-Name: 4cf6e9db757931aba2f300b7869305434d6f2d2b
This commit is contained in:
drh 2004-07-22 01:19:35 +00:00
parent 900dfba8ef
commit 90f5ecb39d
13 changed files with 387 additions and 216 deletions

View File

@ -1,5 +1,5 @@
C Updates\scomments\sin\ssqlite.h.in\sthat\sdescribe\sthe\sdestructor\sparameter\nto\ssqlite3_bind_....\s(CVS\s1842)
D 2004-07-21T15:21:36
C Initial\simplementation\sof\svariable\spage\ssizes\sand\sthe\stemp_store\spragma.\s(CVS\s1843)
D 2004-07-22T01:19:35
F Makefile.in 4a5e570a9e2d35b09c31b3cf01b78cea764ade4b
F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
@ -25,11 +25,11 @@ F sqlite.1 83f4a9d37bdf2b7ef079a82d54eaf2e3509ee6ea
F sqlite.pc.in 30552343140c53304c2a658c080fbe810cd09ca2
F sqlite3.def 7610bb4092dcfa7db8fe6d9a92d3e51adce23566
F sqlite3.pc.in 985b9bf34192a549d7d370e0f0b6b34a4f61369a
F src/attach.c 5e37aaac0907edad5da8ba785b94f04fbb4003d7
F src/attach.c 9e3fcd504aa5760b3d95f4a0bceca075ca1c96a7
F src/auth.c 60db23b98bb94c8b0178180faaf49dc116674217
F src/btree.c 23d4cbe6f612a77738caa636c48dd38e1efdfd76
F src/btree.h 934d0ad30b5b419e9291a11da878be349df2277e
F src/build.c a4b1e80b13c570c7c962f500fa58045450b5a0cd
F src/btree.c 385dceb1ac0eb8bac6e60ad371c8c8ba809438d8
F src/btree.h 02fd2c26b739f38e43493f52f381d9e7d688bb8e
F src/build.c 3a1356286569266873d5d1c910e7797a3bfd5761
F src/date.c e1bb384a7856c18dce9cadb0afbe6934ba5ddb00
F src/delete.c e81545e546f6bc87d7508a93a09ca70695265af3
F src/encode.c a876af473d1d636faa3dca51c7571f2e007eea37
@ -39,7 +39,7 @@ F src/hash.c f0a2f22c2a7052d67053b5f4690ea3010bb3fb9f
F src/hash.h 762d95f1e567664d1eafc1687de755626be962fb
F src/insert.c d99ffe87e1e1397f4233afcd06841d52d6b17b18
F src/legacy.c ad23746f15f67e34577621b1875f639c94839e1f
F src/main.c 4f3c3f0f9e9aa6d6595d6fcb0d3cdd4d31191554
F src/main.c 447db2fb6121360814afd725ee93c22d6eef8e7f
F src/md5.c 7ae1c39044b95de2f62e066f47bb1deb880a1070
F src/os.h d1780e0db95cad01f213d48da22ab490eb4fd345
F src/os_common.h fe9604754116bd2f2702d58f82d2d8b89998cb21
@ -51,21 +51,21 @@ F src/os_unix.c 02a08065f90ca2737514cdc19d60eb3c4b98fa6b
F src/os_unix.h f3097815e041e82e24d92505e1ff61ba24172d13
F src/os_win.c 54181eb73cb4783c4241feca9eaa490768b39008
F src/os_win.h babd4e912967c6b09088cfe38a45e8005a07ba44
F src/pager.c 53a310a7539c7550dc7cbad8e46c62926a40fb31
F src/pager.h 269b6cfc114dba0148203446e41dd19f9647dd53
F src/pager.c 1354e8f80889a8c967f4bc4ee2723485624eb6e7
F src/pager.h 67739fe649f33be55dba522ca8a9cc4e42d14f71
F src/parse.y 1c22ccb2b60237a7263873892a4d580ea5e53536
F src/pragma.c 8326df8c400f573eb43004dfb8e53e5102acb3e4
F src/pragma.c c8be18093f0492f9983406647808781ca0073d8b
F src/printf.c 36090f6d7b4946539de97c1850675ce55ef66c16
F src/random.c eff68e3f257e05e81eae6c4d50a51eb88beb4ff3
F src/select.c aefda626660086addca4ce85c34aeef5d0f44c25
F src/shell.c ebec5da57ea401f4886eefc790917b939d94d595
F src/sqlite.h.in f43cde2bf8a92c09653358f30b2312424464ed37
F src/sqliteInt.h 788b13a74c421ab68068ab7fe50ec68ee22db1be
F src/sqliteInt.h 17ed61c040c1e47e1dd660daef3adda9ea9cb4fb
F src/table.c 4521c278892f60e4d630788c0ea5cf4db1e75c49
F src/tclsqlite.c 62848128011e59291902c6e5c6f910c05956fcbb
F src/test1.c 004885b49a7b5a594192f137c671135920f64c94
F src/test2.c dafd8bd314a554bf376c6d3a8c83fd69219f5a40
F src/test3.c d0c56667e89f79ad0f060fdf010d1c34a4bc2988
F src/test2.c f4c2f3928f1998fd8cb75a81e33a60e025ea85d4
F src/test3.c 8576bb977937265e2c1a4d3fab3793e1974153e8
F src/test4.c a921a69821fd30209589228e64f94e9f715b6fe2
F src/test5.c b001fa7f1b9e2dc5c2331de62fc641b5ab2bd7a1
F src/tokenize.c 900374b6b37f04748bcd48c2d29a41c251542935
@ -237,7 +237,7 @@ F www/tclsqlite.tcl 06a86cba4d7fc88e2bcd633b57702d3d16abebb5
F www/vdbe.tcl 59288db1ac5c0616296b26dce071c36cb611dfe9
F www/version3.tcl 092a01f5ef430d2c4acc0ae558d74c4bb89638a0
F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4
P df306ad9ee522b20f017be0be83d9e071d525f8e
R ae7b12b9273ae356dcc22ade3f89aa5e
P 166eb60614d958674469d6661c694aa5955ada7b
R 870b048870db5bdcb9c6b07388f49a9f
U drh
Z 985db816d659e2b46dad451a399fdfd0
Z f55d5698fe1367622b023c25ee34d112

View File

@ -1 +1 @@
166eb60614d958674469d6661c694aa5955ada7b
4cf6e9db757931aba2f300b7869305434d6f2d2b

View File

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

View File

@ -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;
}
@ -1059,6 +1059,14 @@ int sqlite3BtreeClose(Btree *pBt){
return SQLITE_OK;
}
/*
** 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.
**
@ -1092,6 +1100,31 @@ int sqlite3BtreeSetSafetyLevel(Btree *pBt, int level){
return SQLITE_OK;
}
/*
** 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
*/

View File

@ -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*);

View File

@ -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 */
){

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.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;
}
/*

View File

@ -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,12 +1497,19 @@ 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
@ -1524,6 +1533,28 @@ void sqlite3pager_set_reiniter(Pager *pPager, void (*xReinit)(void*,int)){
pPager->xReiniter = xReinit;
}
/*
** 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);
}

View File

@ -13,42 +13,27 @@
** 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.
*/
@ -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);

View File

@ -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>
@ -71,6 +71,56 @@ static int getSafetyLevel(char *z){
return 1;
}
/*
** 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.
@ -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 cache_size
** PRAGMA cache_size=N
** 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 [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 synchronous
** PRAGMA synchronous=OFF|ON|NORMAL|FULL
** 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 [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
/*

View File

@ -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 */
@ -311,20 +326,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.
**
@ -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*);

View File

@ -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"
@ -55,6 +55,11 @@ static char *errorName(int rc){
return zName;
}
/*
** Page size and reserved size used for testing.
*/
static int test_pagesize = 1024;
/*
** Usage: pager_open FILENAME N-PAGE
**
@ -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;
}

View File

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