]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Initial implementation of variable page sizes and the temp_store pragma. (CVS 1843)
authordrh <drh@noemail.net>
Thu, 22 Jul 2004 01:19:35 +0000 (01:19 +0000)
committerdrh <drh@noemail.net>
Thu, 22 Jul 2004 01:19:35 +0000 (01:19 +0000)
FossilOrigin-Name: 4cf6e9db757931aba2f300b7869305434d6f2d2b

13 files changed:
manifest
manifest.uuid
src/attach.c
src/btree.c
src/btree.h
src/build.c
src/main.c
src/pager.c
src/pager.h
src/pragma.c
src/sqliteInt.h
src/test2.c
src/test3.c

index 5cdeab9b5b884a6517ab22ee52aaee4af66dc28f..2d3a0bffd160b29022e88d84cd0247dd90c8da3e 100644 (file)
--- a/manifest
+++ b/manifest
@@ -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
index 3dd913d735b9fbb0c4d12f4956b5bef42122a06d..280984cb7afe5265ec07cbe708df19040108ed69 100644 (file)
@@ -1 +1 @@
-166eb60614d958674469d6661c694aa5955ada7b
\ No newline at end of file
+4cf6e9db757931aba2f300b7869305434d6f2d2b
\ No newline at end of file
index dc8f99c33d1cbfc5e918b134b6c385d7d5a97bb7..1679abf598f915b6e5f11c8df5e27b8b37a11979 100644 (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);
index 6bfe24cf4302806ad1e9aa5bd0f8f6e3775e8b77..fcee691769416f44af920be27ef6e93cfa2b81a7 100644 (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
 #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
   */
index 73ee7341ac5c5ccd337f7ebe1d45d21b55b862ed..19261b232014cb5e82a31fa06a2e2ab63b579a08 100644 (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*);
index 2acf308501114213cda47e212009fd132859947c..7f27985f245394d4f2358410bdd76388ad48a111 100644 (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 */
 ){
index 2bf89a774f05bcd0b6c47cbc546d25e8d7d76e48..24a4c19c49f59987d640fe0d6c55cb216e0c9a23 100644 (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;
 }
 
 /*
index 3f5b9fff632acbd7156d476d08d2f33dec8886f8..fc7bce9eded02ce7403beefe5df819cf583cc9ae 100644 (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);
   }
index d0d19535553a0cf73a2b14734aceefb35b702c40..cb4a772c52c296050a2b3bf84382e1bb667aab61 100644 (file)
 ** 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);
index 411672a41694ed8c3731c7841104ce98d791acd3..5c865f5f651e7c5eba84346bf5ffbf0e95f361d6 100644 (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 [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
 
   /*
index 6296648272ab507d835cbdb5bddbb05fa49ec06b..1db96f2b78d479923302c901be1eeac1829bf9cb 100644 (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*);
index 074dc4796fad6e4c0d1fcd105f69fdcb26d19c49..4b98925a93dc74997349facb80cd903c8778da7f 100644 (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;
 }
index 70a4617f235b83e6ad08ab6bf183889e51071280..9904f36e7880f4ffef063a5f28f5f667246cf5b4 100644 (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);