diff --git a/manifest b/manifest index 3b60813fd7..b98709235e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sbug\sin\sthe\snew\sfull-sync\sjournal\sformat.\s(CVS\s1733) -D 2004-06-26T01:48:19 +C Remove\sdefault_synchronous\sand\stemp_store\spragmas.\sAllow\sthe\ssafety-level\nand\scache-size\sto\sbe\sset\sfor\sattached\sdatabases.\s(CVS\s1735) +D 2004-06-26T06:37:07 F Makefile.in cb7a9889c38723f72b2506c4236ff30a05ff172b F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457 F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd @@ -24,7 +24,7 @@ F spec.template a38492f1c1dd349fc24cb0565e08afc53045304b F sqlite.1 83f4a9d37bdf2b7ef079a82d54eaf2e3509ee6ea F sqlite.pc.in 30552343140c53304c2a658c080fbe810cd09ca2 F sqlite3.def 26f4e7b0a3fbaa55701e020fdec429f1594e2866 -F src/attach.c 05102e2e8ac43ce639d07b47a99c7772a62420e6 +F src/attach.c b105aeb8c82fbd097c5067dddde90d5f7fadf8dd F src/auth.c 60db23b98bb94c8b0178180faaf49dc116674217 F src/btree.c 0591368af031a0ecc4620140dfdaa177b82885a1 F src/btree.h 32f96abef464cf8765b23ca669acfe90d191fcc5 @@ -38,7 +38,7 @@ F src/hash.c 440c2f8cb373ee1b4e13a0988489c7cd95d55b6f F src/hash.h 762d95f1e567664d1eafc1687de755626be962fb F src/insert.c d99ffe87e1e1397f4233afcd06841d52d6b17b18 F src/legacy.c ad23746f15f67e34577621b1875f639c94839e1f -F src/main.c 2a4f3fe32ee6357b5b914ab5e2bd0979202570f4 +F src/main.c 7a5afce156d14727a49b60ffe6ab21bcae27e6f3 F src/md5.c 7ae1c39044b95de2f62e066f47bb1deb880a1070 F src/os.h d1780e0db95cad01f213d48da22ab490eb4fd345 F src/os_common.h ba1b7306e16e2091718f2c48db0fe6c1d7a31bb8 @@ -52,14 +52,14 @@ F src/os_win.c 84549f6cc815237533c5d0eb3697352b03478d96 F src/os_win.h babd4e912967c6b09088cfe38a45e8005a07ba44 F src/pager.c e3969171742e7d9681977703feed4853f5ee206a F src/pager.h bc58d32a9dee464f7268fb68652c130a4216e438 -F src/parse.y 097438674976355a10cf177bd97326c548820b86 -F src/pragma.c 0750e1c360647dbe0a991f16133b0fe5e42e5039 +F src/parse.y e19e066e726a31d7b2d3e6475bdf55f7e339f8a3 +F src/pragma.c 16713c1bc440ccd9982a27fb4b38e1a1c95ffd29 F src/printf.c 3090c8ff397d549bc0de09b16d8ab7fd37a0c3f7 F src/random.c eff68e3f257e05e81eae6c4d50a51eb88beb4ff3 F src/select.c f02a65af34231031896e8442161cb5251e191e75 F src/shell.c 24b641700c9d90f361fcfa4f432c5b4aff704e6d F src/sqlite.h.in b70fded2bdfeaddfb06adea3888118b722975136 -F src/sqliteInt.h dd796b6abc6d50505fe33c54f0143d7000681a41 +F src/sqliteInt.h ed55c1f149875b6484798381e6933f5f5ad1a4ce F src/table.c af14284fa36c8d41f6829e3f2819dce07d3e2de2 F src/tclsqlite.c 8d093146332b2f0cbf2a8ebe8597d481619308a3 F src/test1.c e4e0ae8af8040c848ef35f92e6a22b2245b9b873 @@ -141,7 +141,7 @@ F test/notnull.test 7a08117a71e74b0321aaa937dbeb41a09d6eb1d0 F test/null.test 64730a1c32955e5cc510b7632fed6b9929a4029a F test/pager.test 059cc5c58d3b5a851343dff8c56cf7286425d03a F test/pager2.test 55469c7c1c1a54d6b32d7b3cc99001e90101a1ce -F test/pragma.test e09ac12edbdac81d21ca88084fef376c7667f5b0 +F test/pragma.test a0dac4320e130e31e855bbdb935645d7c45d6340 F test/printf.test 1eb584b7272d1abdfe117b2ef7cf3376ae8e4e06 F test/progress.test 7542a6ac7894a1b7730c1f9a27f3f8b9388a4d25 x F test/quick.test 4c0b3eabe2e0e606622d63d7d61ef6efb3ce156b @@ -229,7 +229,7 @@ F www/tclsqlite.tcl 19191cf2a1010eaeff74c51d83fd5f5a4d899075 F www/vdbe.tcl 59288db1ac5c0616296b26dce071c36cb611dfe9 F www/version3.tcl 563ba3ac02f64da27ab17f3edbe8e56bfd0293fb F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4 -P dfab1e9ac0fbe57fe4a1cbe6c363ef43b3b075ef -R e246eb7b8fa1d2e1a6e20fbeb7cc5c16 +P 02bd3acd7efde9cc6b67c97e98db9f4b62d27877 +R 609621fb2d8c2cbffc869dbeea94770a U danielk1977 -Z ead895d5ca480d6e5d884e35379e8164 +Z 231b7ef4aa565faa68238895f77436c5 diff --git a/manifest.uuid b/manifest.uuid index f5484757e0..2f56368b9f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -02bd3acd7efde9cc6b67c97e98db9f4b62d27877 \ No newline at end of file +212de3ce66f746036cb2267a9f924fd55fa2f37a \ No newline at end of file diff --git a/src/attach.c b/src/attach.c index 9468f203a4..a8808d47da 100644 --- a/src/attach.c +++ b/src/attach.c @@ -11,7 +11,7 @@ ************************************************************************* ** This file contains code used to implement the ATTACH and DETACH commands. ** -** $Id: attach.c,v 1.17 2004/06/19 16:06:11 drh Exp $ +** $Id: attach.c,v 1.18 2004/06/26 06:37:07 danielk1977 Exp $ */ #include "sqliteInt.h" @@ -84,6 +84,7 @@ void sqlite3Attach(Parse *pParse, Token *pFilename, Token *pDbname, Token *pKey) sqlite3HashInit(&aNew->trigHash, SQLITE_HASH_STRING, 0); sqlite3HashInit(&aNew->aFKey, SQLITE_HASH_STRING, 1); aNew->zName = zName; + aNew->safety_level = 3; rc = sqlite3BtreeFactory(db, zFile, 0, MAX_PAGES, &aNew->pBt); if( rc ){ sqlite3ErrorMsg(pParse, "unable to open database: %s", zFile); diff --git a/src/main.c b/src/main.c index 20f7983d60..7d15ceb7c9 100644 --- a/src/main.c +++ b/src/main.c @@ -14,7 +14,7 @@ ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** -** $Id: main.c,v 1.233 2004/06/22 12:13:55 drh Exp $ +** $Id: main.c,v 1.234 2004/06/26 06:37:07 danielk1977 Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -218,9 +218,9 @@ static int sqlite3InitOne(sqlite *db, int iDb, char **pzErrMsg){ ** meta[0] Schema cookie. Changes with each schema change. ** meta[1] File format of schema layer. ** meta[2] Size of the page cache. - ** meta[3] Synchronous setting. 1:off, 2:normal, 3:full + ** meta[3] ** meta[4] Db text encoding. 1:UTF-8 3:UTF-16 LE 4:UTF-16 BE - ** meta[5] Pragma temp_store value. See comments on BtreeFactory + ** meta[5] ** meta[6] ** meta[7] ** meta[8] @@ -265,16 +265,11 @@ static int sqlite3InitOne(sqlite *db, int iDb, char **pzErrMsg){ } } - if( iDb==0 ){ - size = meta[2]; - if( size==0 ){ size = MAX_PAGES; } - db->cache_size = size; - db->safety_level = meta[3]; - if( meta[5]>0 && meta[5]<=2 && db->temp_store==0 ){ - db->temp_store = meta[5]; - } - if( db->safety_level==0 ) db->safety_level = 2; + size = meta[2]; + if( size==0 ){ size = MAX_PAGES; } + db->aDb[iDb].cache_size = size; + if( iDb==0 ){ db->file_format = meta[1]; if( db->file_format==0 ){ /* This happens if the database was initially empty */ @@ -291,8 +286,7 @@ static int sqlite3InitOne(sqlite *db, int iDb, char **pzErrMsg){ return SQLITE_ERROR; } - sqlite3BtreeSetCacheSize(db->aDb[iDb].pBt, db->cache_size); - sqlite3BtreeSetSafetyLevel(db->aDb[iDb].pBt, meta[3]==0 ? 2 : meta[3]); + sqlite3BtreeSetCacheSize(db->aDb[iDb].pBt, db->aDb[iDb].cache_size); /* Read the schema information out of the schema tables */ @@ -807,22 +801,6 @@ 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 */ @@ -837,7 +815,10 @@ int sqlite3BtreeFactory( if( omitJournal ){ btree_flags |= BTREE_OMIT_JOURNAL; } - if( !zFilename ){ + 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. + */ btree_flags |= BTREE_MEMORY; } @@ -1127,12 +1108,6 @@ static int openDatabase( sqlite3_create_collation(db, "NOCASE", SQLITE_UTF8, 0, nocaseCollatingFunc); /* Open the backend database driver */ - if( zFilename[0]==':' && strcmp(zFilename,":memory:")==0 ){ - db->temp_store = 2; - db->nMaster = 0; /* Disable atomic multi-file commit for :memory: */ - }else{ - db->nMaster = -1; /* Size of master journal filename initially unknown */ - } rc = sqlite3BtreeFactory(db, zFilename, 0, MAX_PAGES, &db->aDb[0].pBt); if( rc!=SQLITE_OK ){ sqlite3Error(db, rc, 0); @@ -1142,6 +1117,11 @@ static int openDatabase( db->aDb[0].zName = "main"; db->aDb[1].zName = "temp"; + /* The default safety_level for the main database is 'full' for the temp + ** database it is 'NONE'. This matches the pager layer defaults. */ + db->aDb[0].safety_level = 3; + db->aDb[1].safety_level = 1; + /* Register all built-in functions, but do not attempt to read the ** database schema yet. This is delayed until the first time the database ** is accessed. diff --git a/src/parse.y b/src/parse.y index 5e0e1cc847..567d228008 100644 --- a/src/parse.y +++ b/src/parse.y @@ -14,7 +14,7 @@ ** the parser. Lemon will also generate a header file containing ** numeric codes for all of the tokens. ** -** @(#) $Id: parse.y,v 1.127 2004/06/09 09:55:18 danielk1977 Exp $ +** @(#) $Id: parse.y,v 1.128 2004/06/26 06:37:07 danielk1977 Exp $ */ %token_prefix TK_ %token_type {Token} @@ -782,12 +782,14 @@ cmd ::= VACUUM nm(X). {sqlite3Vacuum(pParse,&X);} ///////////////////////////// The PRAGMA command ///////////////////////////// // -cmd ::= PRAGMA ids(X) EQ nm(Y). {sqlite3Pragma(pParse,&X,&Y,0);} -cmd ::= PRAGMA ids(X) EQ ON(Y). {sqlite3Pragma(pParse,&X,&Y,0);} -cmd ::= PRAGMA ids(X) EQ plus_num(Y). {sqlite3Pragma(pParse,&X,&Y,0);} -cmd ::= PRAGMA ids(X) EQ minus_num(Y). {sqlite3Pragma(pParse,&X,&Y,1);} -cmd ::= PRAGMA ids(X) LP nm(Y) RP. {sqlite3Pragma(pParse,&X,&Y,0);} -cmd ::= PRAGMA ids(X). {sqlite3Pragma(pParse,&X,&X,0);} +cmd ::= PRAGMA nm(X) dbnm(Z) EQ nm(Y). {sqlite3Pragma(pParse,&X,&Z,&Y,0);} +cmd ::= PRAGMA nm(X) dbnm(Z) EQ ON(Y). {sqlite3Pragma(pParse,&X,&Z,&Y,0);} +cmd ::= PRAGMA nm(X) dbnm(Z) EQ plus_num(Y). {sqlite3Pragma(pParse,&X,&Z,&Y,0);} +cmd ::= PRAGMA nm(X) dbnm(Z) EQ minus_num(Y). { + sqlite3Pragma(pParse,&X,&Z,&Y,1); +} +cmd ::= PRAGMA nm(X) dbnm(Z) LP nm(Y) RP. {sqlite3Pragma(pParse,&X,&Z,&Y,0);} +cmd ::= PRAGMA nm(X) dbnm(Z). {sqlite3Pragma(pParse,&X,&Z,0,0);} plus_num(A) ::= plus_opt number(X). {A = X;} minus_num(A) ::= MINUS number(X). {A = X;} number(A) ::= INTEGER(X). {A = X;} diff --git a/src/pragma.c b/src/pragma.c index a4fba9fa23..54c9391ce9 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -11,7 +11,7 @@ ************************************************************************* ** This file contains code used to implement the PRAGMA command. ** -** $Id: pragma.c,v 1.52 2004/06/21 09:06:42 danielk1977 Exp $ +** $Id: pragma.c,v 1.53 2004/06/26 06:37:07 danielk1977 Exp $ */ #include "sqliteInt.h" #include @@ -71,46 +71,6 @@ 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->autoCommit ){ - 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; -} - /* ** 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. @@ -157,27 +117,43 @@ static int flagPragma(Parse *pParse, const char *zLeft, const char *zRight){ ** ** Pragmas are of this form: ** -** PRAGMA id = value +** PRAGMA [database.]id [= value] ** ** 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. */ -void sqlite3Pragma(Parse *pParse, Token *pLeft, Token *pRight, int minusFlag){ - char *zLeft = 0; - char *zRight = 0; +void sqlite3Pragma( + Parse *pParse, + Token *pId1, /* First part of [database.]id field */ + Token *pId2, /* Second part of [database.]id field, or NULL */ + Token *pValue, /* Token for , or NULL */ + int minusFlag /* True if a '-' sign preceded */ +){ + char *zLeft = 0; /* Nul-terminated UTF-8 string */ + char *zRight = 0; /* Nul-terminated UTF-8 string , or NULL */ + const char *zDb = 0; /* The database name */ + Token *pId; /* Pointer to token */ + int iDb; /* Database index for */ sqlite *db = pParse->db; Vdbe *v = sqlite3GetVdbe(pParse); if( v==0 ) return; - zLeft = sqlite3NameFromToken(pLeft); + /* Interpret the [database.] part of the pragma statement. iDb is the + ** index of the database this pragma is being applied to in db.aDb[]. */ + iDb = sqlite3TwoPartName(pParse, pId1, pId2, &pId); + if( iDb<0 ) return; + + zLeft = sqlite3NameFromToken(pId); if( minusFlag ){ zRight = 0; - sqlite3SetNString(&zRight, "-", 1, pRight->z, pRight->n, 0); + sqlite3SetNString(&zRight, "-", 1, pValue->z, pValue->n, 0); }else{ - zRight = sqlite3NameFromToken(pRight); + zRight = sqlite3NameFromToken(pValue); } - if( sqlite3AuthCheck(pParse, SQLITE_PRAGMA, zLeft, zRight, 0) ){ + + zDb = ((iDb>0)?db->aDb[iDb].zName:0); + if( sqlite3AuthCheck(pParse, SQLITE_PRAGMA, zLeft, zRight, zDb) ){ goto pragma_out; } @@ -199,7 +175,7 @@ void sqlite3Pragma(Parse *pParse, Token *pLeft, Token *pRight, int minusFlag){ */ if( sqlite3StrICmp(zLeft,"default_cache_size")==0 ){ static VdbeOpList getCacheSize[] = { - { OP_ReadCookie, 0, 2, 0}, + { OP_ReadCookie, 0, 2, 0}, /* 0 */ { OP_AbsValue, 0, 0, 0}, { OP_Dup, 0, 0, 0}, { OP_Integer, 0, 0, 0}, @@ -212,24 +188,25 @@ void sqlite3Pragma(Parse *pParse, Token *pLeft, Token *pRight, int minusFlag){ pParse->nErr++; goto pragma_out; } - if( pRight->z==pLeft->z ){ + if( !zRight ){ sqlite3VdbeSetNumCols(v, 1); sqlite3VdbeSetColName(v, 0, "cache_size", P3_STATIC); addr = sqlite3VdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize); + sqlite3VdbeChangeP1(v, addr, iDb); sqlite3VdbeChangeP1(v, addr+5, MAX_PAGES); }else{ int size = atoi(zRight); if( size<0 ) size = -size; - sqlite3BeginWriteOperation(pParse, 0, 0); + sqlite3BeginWriteOperation(pParse, 0, iDb); sqlite3VdbeAddOp(v, OP_Integer, size, 0); - sqlite3VdbeAddOp(v, OP_ReadCookie, 0, 2); + sqlite3VdbeAddOp(v, OP_ReadCookie, iDb, 2); addr = sqlite3VdbeAddOp(v, OP_Integer, 0, 0); sqlite3VdbeAddOp(v, OP_Ge, 0, addr+3); sqlite3VdbeAddOp(v, OP_Negative, 0, 0); - sqlite3VdbeAddOp(v, OP_SetCookie, 0, 2); + sqlite3VdbeAddOp(v, OP_SetCookie, iDb, 2); sqlite3EndWriteOperation(pParse); - db->cache_size = db->cache_size<0 ? -size : size; - sqlite3BtreeSetCacheSize(db->aDb[0].pBt, db->cache_size); + db->aDb[iDb].cache_size = size; + sqlite3BtreeSetCacheSize(db->aDb[iDb].pBt, db->aDb[iDb].cache_size); } }else @@ -255,9 +232,9 @@ void sqlite3Pragma(Parse *pParse, Token *pLeft, Token *pRight, int minusFlag){ pParse->nErr++; goto pragma_out; } - if( pRight->z==pLeft->z ){ - int size = db->cache_size;; - if( size<0 ) size = -size; + 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); @@ -265,77 +242,8 @@ void sqlite3Pragma(Parse *pParse, Token *pLeft, Token *pRight, int minusFlag){ }else{ int size = atoi(zRight); if( size<0 ) size = -size; - if( db->cache_size<0 ) size = -size; - db->cache_size = size; - sqlite3BtreeSetCacheSize(db->aDb[0].pBt, db->cache_size); - } - }else - - /* - ** PRAGMA default_synchronous - ** PRAGMA default_synchronous=ON|OFF|NORMAL|FULL - ** - ** The first form returns the persistent value of the "synchronous" setting - ** that is stored in the database. This is the synchronous setting that - ** is used whenever the database is opened unless overridden by a separate - ** "synchronous" pragma. The second form changes the persistent and the - ** local synchronous setting to the value given. - ** - ** If synchronous is OFF, SQLite does not attempt any fsync() systems calls - ** to make sure data is committed to disk. Write operations are very fast, - ** but a power failure can leave the database in an inconsistent state. - ** If synchronous is ON or NORMAL, SQLite will do an fsync() system call to - ** make sure data is being written to disk. The risk of corruption due to - ** a power loss in this mode is negligible but non-zero. If synchronous - ** is FULL, extra fsync()s occur to reduce the risk of corruption to near - ** zero, but with a write performance penalty. The default mode is NORMAL. - */ - if( sqlite3StrICmp(zLeft,"default_synchronous")==0 ){ - static VdbeOpList getSync[] = { - { OP_ReadCookie, 0, 3, 0}, - { OP_Dup, 0, 0, 0}, - { OP_If, 0, 0, 0}, /* 2 */ - { OP_ReadCookie, 0, 2, 0}, - { OP_Integer, 0, 0, 0}, - { OP_Lt, 0, 5, 0}, - { OP_AddImm, 1, 0, 0}, - { OP_Callback, 1, 0, 0}, - { OP_Halt, 0, 0, 0}, - { OP_AddImm, -1, 0, 0}, /* 9 */ - { OP_Callback, 1, 0, 0} - }; - int addr; - if( SQLITE_OK!=sqlite3ReadSchema(pParse->db, &pParse->zErrMsg) ){ - pParse->nErr++; - goto pragma_out; - } - if( pRight->z==pLeft->z ){ - sqlite3VdbeSetNumCols(v, 1); - sqlite3VdbeSetColName(v, 0, "synchronous", P3_STATIC); - addr = sqlite3VdbeAddOpList(v, ArraySize(getSync), getSync); - sqlite3VdbeChangeP2(v, addr+2, addr+9); - }else{ - int size = db->cache_size; - if( size<0 ) size = -size; - sqlite3BeginWriteOperation(pParse, 0, 0); - sqlite3VdbeAddOp(v, OP_ReadCookie, 0, 2); - sqlite3VdbeAddOp(v, OP_Dup, 0, 0); - addr = sqlite3VdbeAddOp(v, OP_Integer, 0, 0); - sqlite3VdbeAddOp(v, OP_Ne, 0, addr+3); - sqlite3VdbeAddOp(v, OP_AddImm, MAX_PAGES, 0); - sqlite3VdbeAddOp(v, OP_AbsValue, 0, 0); - db->safety_level = getSafetyLevel(zRight)+1; - if( db->safety_level==1 ){ - sqlite3VdbeAddOp(v, OP_Negative, 0, 0); - size = -size; - } - sqlite3VdbeAddOp(v, OP_SetCookie, 0, 2); - sqlite3VdbeAddOp(v, OP_Integer, db->safety_level, 0); - sqlite3VdbeAddOp(v, OP_SetCookie, 0, 3); - sqlite3EndWriteOperation(pParse); - db->cache_size = size; - sqlite3BtreeSetCacheSize(db->aDb[0].pBt, db->cache_size); - sqlite3BtreeSetSafetyLevel(db->aDb[0].pBt, db->safety_level); + db->aDb[iDb].cache_size = size; + sqlite3BtreeSetCacheSize(db->aDb[iDb].pBt, db->aDb[iDb].cache_size); } }else @@ -356,19 +264,19 @@ void sqlite3Pragma(Parse *pParse, Token *pLeft, Token *pRight, int minusFlag){ pParse->nErr++; goto pragma_out; } - if( pRight->z==pLeft->z ){ + if( !zRight ){ sqlite3VdbeSetNumCols(v, 1); sqlite3VdbeSetColName(v, 0, "synchronous", P3_STATIC); - sqlite3VdbeAddOp(v, OP_Integer, db->safety_level-1, 0); + sqlite3VdbeAddOp(v, OP_Integer, db->aDb[iDb].safety_level-1, 0); sqlite3VdbeAddOpList(v, ArraySize(getSync), getSync); }else{ - int size = db->cache_size; - if( size<0 ) size = -size; - db->safety_level = getSafetyLevel(zRight)+1; - if( db->safety_level==1 ) size = -size; - db->cache_size = size; - sqlite3BtreeSetCacheSize(db->aDb[0].pBt, db->cache_size); - sqlite3BtreeSetSafetyLevel(db->aDb[0].pBt, db->safety_level); + 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); + } } }else @@ -386,6 +294,18 @@ void sqlite3Pragma(Parse *pParse, Token *pLeft, Token *pRight, int minusFlag){ /* The flagPragma() call also generates any necessary code */ }else + /* + ** PRAGMA table_info() + ** + ** Return a single row for each column of the named table. The columns of + ** the returned data set are: + ** + ** cid: Column id (numbered from left to right, starting at 0) + ** name: Column name + ** type: Column declaration type. + ** notnull: True if 'NOT NULL' is part of column declaration + ** dflt_value: The default value for the column, if any. + */ if( sqlite3StrICmp(zLeft, "table_info")==0 ){ Table *pTab; if( SQLITE_OK!=sqlite3ReadSchema(pParse->db, &pParse->zErrMsg) ){ @@ -530,67 +450,6 @@ void sqlite3Pragma(Parse *pParse, Token *pLeft, Token *pRight, int minusFlag){ } }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 ){ - static VdbeOpList getTmpDbLoc[] = { - { OP_Callback, 1, 0, 0}, - }; - if( SQLITE_OK!=sqlite3ReadSchema(pParse->db, &pParse->zErrMsg) ){ - pParse->nErr++; - goto pragma_out; - } - if( pRight->z==pLeft->z ){ - sqlite3VdbeAddOp(v, OP_Integer, db->temp_store, 0); - sqlite3VdbeSetNumCols(v, 1); - sqlite3VdbeSetColName(v, 0, "temp_store", P3_STATIC); - sqlite3VdbeAddOpList(v, ArraySize(getTmpDbLoc), getTmpDbLoc); - }else{ - changeTempStorage(pParse, zRight); - } - }else - - /* - ** PRAGMA default_temp_store - ** PRAGMA default_temp_store = "default"|"memory"|"file" - ** - ** Return or set the value of the persistent temp_store flag. Any - ** change does not take effect until 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, "default_temp_store")==0 ){ - static VdbeOpList getTmpDbLoc[] = { - { OP_ReadCookie, 0, 5, 0}, - { OP_Callback, 1, 0, 0}}; - if( SQLITE_OK!=sqlite3ReadSchema(pParse->db, &pParse->zErrMsg) ){ - pParse->nErr++; - goto pragma_out; - } - if( pRight->z==pLeft->z ){ - sqlite3VdbeSetNumCols(v, 1); - sqlite3VdbeSetColName(v, 0, "temp_store", P3_STATIC); - sqlite3VdbeAddOpList(v, ArraySize(getTmpDbLoc), getTmpDbLoc); - }else{ - sqlite3BeginWriteOperation(pParse, 0, 0); - sqlite3VdbeAddOp(v, OP_Integer, getTempStore(zRight), 0); - sqlite3VdbeAddOp(v, OP_SetCookie, 0, 5); - sqlite3EndWriteOperation(pParse); - } - }else - #ifndef NDEBUG if( sqlite3StrICmp(zLeft, "parser_trace")==0 ){ extern void sqlite3ParserTrace(FILE*, char *); @@ -779,7 +638,7 @@ void sqlite3Pragma(Parse *pParse, Token *pLeft, Token *pRight, int minusFlag){ }; struct EncName *pEnc; encnames[6].enc = encnames[7].enc = SQLITE_UTF16NATIVE; - if( pRight->z==pLeft->z ){ /* "PRAGMA encoding" */ + if( !zRight ){ /* "PRAGMA encoding" */ if( SQLITE_OK!=sqlite3ReadSchema(pParse->db, &pParse->zErrMsg) ){ pParse->nErr++; goto pragma_out; diff --git a/src/sqliteInt.h b/src/sqliteInt.h index e6ad4a517d..deaca08262 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.299 2004/06/22 12:13:55 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.300 2004/06/26 06:37:07 danielk1977 Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ @@ -67,19 +67,6 @@ */ #define MAX_ATTACHED 10 -/* -** The next macro is used to determine where TEMP tables and indices -** are stored. Possible values: -** -** 0 Always use a temporary files -** 1 Use a file unless overridden by "PRAGMA temp_store" -** 2 Use memory unless overridden by "PRAGMA temp_store" -** 3 Always use memory -*/ -#ifndef TEMP_STORE -# define TEMP_STORE 1 -#endif - /* ** When building SQLite for embedded systems where memory is scarce, ** you can define one or more of the following macros to omit extra @@ -290,6 +277,8 @@ struct Db { 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 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 */ void (*xFreeAux)(void*); /* Routine to free pAux */ }; @@ -335,11 +324,6 @@ struct BusyHandler { /* ** Each database is an instance of the following structure. ** -** The sqlite.temp_store determines where temporary database files -** are stored. If 1, then a file is created to hold those tables. If -** 2, then they are held in memory. 0 means use the default value in -** the TEMP_STORE macro. -** ** The sqlite.lastRowid records the last insert rowid generated by an ** insert statement. Inserts on views do not affect its value. Each ** trigger has its own context, so that lastRowid can be updated inside @@ -369,9 +353,6 @@ 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 safety_level; /* How aggressive at synching data to disk */ - u8 temp_store; /* 1=file, 2=memory, 0=compile-time default */ - int cache_size; /* Number of pages to use in the cache */ int nTable; /* Number of tables in the database */ BusyHandler busyHandler; /* Busy callback */ void *pCommitArg; /* Argument to xCommitCallback() */ @@ -1225,7 +1206,7 @@ void sqlite3ExprDelete(Expr*); ExprList *sqlite3ExprListAppend(ExprList*,Expr*,Token*); void sqlite3ExprListDelete(ExprList*); int sqlite3Init(sqlite*, char**); -void sqlite3Pragma(Parse*,Token*,Token*,int); +void sqlite3Pragma(Parse*,Token*,Token*,Token*,int); void sqlite3ResetInternalSchema(sqlite*, int); void sqlite3BeginParse(Parse*,int); void sqlite3RollbackInternalChanges(sqlite*); diff --git a/test/pragma.test b/test/pragma.test index 365c67a56b..a0c7f37f7e 100644 --- a/test/pragma.test +++ b/test/pragma.test @@ -12,11 +12,21 @@ # # This file implements tests for the PRAGMA command. # -# $Id: pragma.test,v 1.13 2004/06/19 00:16:31 drh Exp $ +# $Id: pragma.test,v 1.14 2004/06/26 06:37:07 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl +# Test organization: +# +# pragma-1.*: Test cache_size, default_cache_size and synchronous on main db. +# pragma-2.*: Test synchronous on attached db. +# pragma-3.*: Test detection of table/index inconsistency by integrity_check. +# pragma-4.*: Test cache_size and default_cache_size on attached db. +# pragma-5.*: Test that pragma synchronous may not be used inside of a +# transaction. +# + # Delete the preexisting database to avoid the special setup # that the "all.test" script does. # @@ -29,18 +39,16 @@ do_test pragma-1.1 { PRAGMA cache_size; PRAGMA default_cache_size; PRAGMA synchronous; - PRAGMA default_synchronous; } -} {2000 2000 1 1} +} {2000 2000 2} do_test pragma-1.2 { execsql { PRAGMA cache_size=1234; PRAGMA cache_size; PRAGMA default_cache_size; PRAGMA synchronous; - PRAGMA default_synchronous; } -} {1234 2000 1 1} +} {1234 2000 2} do_test pragma-1.3 { db close sqlite3 db test.db @@ -48,36 +56,32 @@ do_test pragma-1.3 { PRAGMA cache_size; PRAGMA default_cache_size; PRAGMA synchronous; - PRAGMA default_synchronous; } -} {2000 2000 1 1} +} {2000 2000 2} do_test pragma-1.4 { execsql { PRAGMA synchronous=OFF; PRAGMA cache_size; PRAGMA default_cache_size; PRAGMA synchronous; - PRAGMA default_synchronous; } -} {2000 2000 0 1} +} {2000 2000 0} do_test pragma-1.5 { execsql { PRAGMA cache_size=4321; PRAGMA cache_size; PRAGMA default_cache_size; PRAGMA synchronous; - PRAGMA default_synchronous; } -} {4321 2000 0 1} +} {4321 2000 0} do_test pragma-1.6 { execsql { PRAGMA synchronous=ON; PRAGMA cache_size; PRAGMA default_cache_size; PRAGMA synchronous; - PRAGMA default_synchronous; } -} {4321 2000 1 1} +} {4321 2000 1} do_test pragma-1.7 { db close sqlite3 db test.db @@ -85,84 +89,78 @@ do_test pragma-1.7 { PRAGMA cache_size; PRAGMA default_cache_size; PRAGMA synchronous; - PRAGMA default_synchronous; } -} {2000 2000 1 1} +} {2000 2000 2} do_test pragma-1.8 { - execsql { - PRAGMA default_synchronous=OFF; - PRAGMA cache_size; - PRAGMA default_cache_size; - PRAGMA synchronous; - PRAGMA default_synchronous; - } -} {2000 2000 0 0} -do_test pragma-1.9 { execsql { PRAGMA default_cache_size=123; PRAGMA cache_size; PRAGMA default_cache_size; PRAGMA synchronous; - PRAGMA default_synchronous; } -} {123 123 0 0} -do_test pragma-1.10 { +} {123 123 2} +do_test pragma-1.9 { db close set ::DB [sqlite3 db test.db] execsql { PRAGMA cache_size; PRAGMA default_cache_size; PRAGMA synchronous; - PRAGMA default_synchronous; } -} {123 123 0 0} -do_test pragma-1.11 { +} {123 123 2} +do_test pragma-1.10 { execsql { PRAGMA synchronous=NORMAL; PRAGMA cache_size; PRAGMA default_cache_size; PRAGMA synchronous; - PRAGMA default_synchronous; } -} {123 123 1 0} -do_test pragma-1.12 { +} {123 123 1} +do_test pragma-1.11 { execsql { PRAGMA synchronous=FULL; PRAGMA cache_size; PRAGMA default_cache_size; PRAGMA synchronous; - PRAGMA default_synchronous; } -} {123 123 2 0} -do_test pragma-1.13 { +} {123 123 2} +do_test pragma-1.12 { db close set ::DB [sqlite3 db test.db] execsql { PRAGMA cache_size; PRAGMA default_cache_size; PRAGMA synchronous; - PRAGMA default_synchronous; } -} {123 123 0 0} -do_test pragma-1.14 { +} {123 123 2} + +# Test modifying the safety_level of an attached database. +do_test pragma-2.1 { + file delete -force test2.db + file delete -force test2.db-journal execsql { - PRAGMA default_synchronous=FULL; - PRAGMA cache_size; - PRAGMA default_cache_size; - PRAGMA synchronous; - PRAGMA default_synchronous; - } -} {123 123 2 2} -do_test pragma-1.15 { - db close - set ::DB [sqlite3 db test.db] + ATTACH 'test2.db' AS aux; + } +} {} +do_test pragma-2.2 { execsql { - PRAGMA cache_size; - PRAGMA default_cache_size; - PRAGMA synchronous; - PRAGMA default_synchronous; - } -} {123 123 2 2} + pragma aux.synchronous; + } +} {2} +do_test pragma-2.3 { + execsql { + pragma aux.synchronous = OFF; + pragma aux.synchronous; + pragma synchronous; + } +} {0 2} +do_test pragma-2.4 { + execsql { + pragma aux.synchronous = ON; + pragma synchronous; + pragma aux.synchronous; + } +} {2 1} # Construct a corrupted index and make sure the integrity_check # pragma finds it. @@ -192,150 +190,73 @@ do_test pragma-3.2 { } {{rowid 1 missing from index i2} {wrong # of entries in index i2}} }; # endif has-codec -# Test the temp_store and default_temp_store pragmas -# +do_test pragma-3.3 { + execsql { + DROP INDEX i2; + } +} {} + +# Test modifying the cache_size of an attached database. +do_test pragma-4.1 { + execsql { + pragma aux.cache_size; + pragma aux.default_cache_size; + } +} {2000 2000} do_test pragma-4.2 { execsql { - PRAGMA temp_store='default'; - PRAGMA temp_store; - } -} {0} + pragma aux.cache_size = 50; + pragma aux.cache_size; + pragma aux.default_cache_size; + } +} {50 2000} do_test pragma-4.3 { execsql { - PRAGMA temp_store='file'; - PRAGMA temp_store; - } -} {1} + pragma aux.default_cache_size = 456; + pragma aux.cache_size; + pragma aux.default_cache_size; + } +} {456 456} do_test pragma-4.4 { execsql { - PRAGMA temp_store='memory'; - PRAGMA temp_store; - } -} {2} + pragma cache_size; + pragma default_cache_size; + } +} {123 123} do_test pragma-4.5 { execsql { - PRAGMA default_temp_store='default'; - PRAGMA default_temp_store; - } -} {0} + DETACH aux; + ATTACH 'test3.db' AS aux; + pragma aux.cache_size; + pragma aux.default_cache_size; + } +} {2000 2000} do_test pragma-4.6 { execsql { - PRAGMA temp_store; - } -} {2} -do_test pragma-4.7 { - db close - sqlite3 db test.db - execsql { - PRAGMA temp_store; - } -} {0} -do_test pragma-4.8 { - execsql { - PRAGMA default_temp_store; - } -} {0} -do_test pragma-4.9 { - execsql { - PRAGMA default_temp_store='file'; - PRAGMA default_temp_store; - } -} {1} -do_test pragma-4.10 { - execsql { - PRAGMA temp_store; - } -} {0} -do_test pragma-4.11 { - db close - sqlite3 db test.db - execsql { - PRAGMA temp_store; - } -} {1} -do_test pragma-4.12 { - execsql { - PRAGMA default_temp_store; - } -} {1} -do_test pragma-4.13 { - execsql { - PRAGMA default_temp_store='memory'; - PRAGMA default_temp_store; - } -} {2} -do_test pragma-4.14 { - execsql { - PRAGMA temp_store; - } -} {1} -do_test pragma-4.15 { - db close - sqlite3 db test.db - execsql { - PRAGMA temp_store; - } -} {2} -do_test pragma-4.16 { - execsql { - PRAGMA default_temp_store; - } -} {2} -do_test pragma-4.17 { - execsql { - PRAGMA temp_store='file'; - PRAGMA temp_store - } -} {1} -do_test pragma-4.18 { - execsql { - PRAGMA default_temp_store - } -} {2} -do_test pragma-4.19 { - db close - sqlite3 db test.db - execsql { - PRAGMA temp_store - } -} {2} + DETACH aux; + ATTACH 'test2.db' AS aux; + pragma aux.cache_size; + pragma aux.default_cache_size; + } +} {456 456} -# Changing the TEMP_STORE deletes any existing temporary tables -# -do_test pragma-4.20 { - execsql {SELECT name FROM sqlite_temp_master} -} {} -do_test pragma-4.21 { +# Test that modifying the sync-level in the middle of a transaction is +# disallowed. +do_test pragma-5.0 { execsql { - CREATE TEMP TABLE test1(a,b,c); - SELECT name FROM sqlite_temp_master; - } -} {test1} -do_test pragma-4.22 { - execsql { - PRAGMA temp_store='file'; - SELECT name FROM sqlite_temp_master; - } -} {} -do_test pragma-4.23 { - execsql { - CREATE TEMP TABLE test1(a,b,c); - SELECT name FROM sqlite_temp_master; - } -} {test1} -do_test pragma-4.24 { - execsql { - PRAGMA temp_store='memory'; - SELECT name FROM sqlite_temp_master; - } -} {} -do_test pragma-4.25 { + pragma synchronous; + } +} {2} +do_test pragma-5.1 { catchsql { BEGIN; - PRAGMA temp_store='default'; - COMMIT; - } -} {1 {temporary storage cannot be changed from within a transaction}} -catchsql {COMMIT} + pragma synchronous = OFF; + } +} {1 {Safety level may not be changed inside a transaction}} +do_test pragma-5.2 { + execsql { + pragma synchronous; + } +} {2} finish_test