diff --git a/manifest b/manifest index 4d50a48a0b..177395408a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sdocumentation\sfor\sDEFAULT\sCURRENT_TIME\s&\sco.\s(CVS\s2088) -D 2004-11-11T01:50:30 +C Add\sthe\sschema_cookie\sand\suser_cookie\spragmas.\s(CVS\s2089) +D 2004-11-11T05:10:44 F Makefile.in c4d2416860f472a1e3393714d0372074197565df F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457 F README a01693e454a00cc117967e3f9fdab2d4d52e9bc1 @@ -40,7 +40,7 @@ F src/hash.c a97721a55440b7bea31ffe471bb2f6b4123cddd5 F src/hash.h 1b0c445e1c89ff2aaad9b4605ba61375af001e84 F src/insert.c 8bd40dc5a8e470cba5b9b14211fa88ea0350d2fa F src/legacy.c d58ea507bce885298a2c8c3cbb0f4bff5d47830b -F src/main.c ba1b26f03af4b7f8be3394748123dd671b9ea147 +F src/main.c c7dc54c62c86cab8b2e2883aef607c179eefa611 F src/md5.c 7ae1c39044b95de2f62e066f47bb1deb880a1070 F src/os.h 38258df2db895499b6e2957dbf17f25e0df71667 F src/os_common.h 0e7f428ba0a6c40a61bc56c4e96f493231301b73 @@ -55,7 +55,7 @@ F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b F src/pager.c ee88fcecb081e3635c281bc09d604e934429e2f5 F src/pager.h 9eba8c53dd91eae7f3f90743b2ee242da02a9862 F src/parse.y 02e0d88a6d465f6fd5ea79a200a8c23c92a877dc -F src/pragma.c 44074b93216516b01cafacd85cb10621088693dd +F src/pragma.c bb1c76dae9911b9312997b353c1e316fa603a0c6 F src/printf.c 3d20b21cfecadacecac3fb7274e746cb81d3d357 F src/random.c eff68e3f257e05e81eae6c4d50a51eb88beb4ff3 F src/select.c 156990c636102bb6b8de85e7ff3396a62568476b @@ -156,7 +156,7 @@ F test/pager.test 394455707a079804e8a4e431d12edce831a065f0 F test/pager2.test c7e731ac56a2984a605b032ffd19b9deee820377 F test/pager3.test 647f696a9cf7409df00a1e0047c2eb55585a1b85 F test/pagesize.test 6f94b70ed9645dbe6314b627ae765c5dec8036d9 -F test/pragma.test bde1271384bc415af04d9dd736c073cf7ef33177 +F test/pragma.test 1d2ca2b52e08ed5af81f7f02e4490182bfd2f832 F test/printf.test 92ba4c510b4fc61120ffa4a01820446ed917ae57 F test/progress.test 5ddba78cb6011fba36093973cfb3ac473b8fb96a x F test/quick.test 9e968949a20b5ed5990c03dc45df3781a03c4b1a @@ -246,7 +246,7 @@ F www/nulls.tcl ec35193f92485b87b90a994a01d0171b58823fcf F www/oldnews.tcl 7aa4478e64631859770a5fe4b413919ba6ee8a08 F www/omitted.tcl 7bd62b6f0f53b60c5360895b16b3af8407bbca03 F www/opcode.tcl dafa030a5a3cc24a2f9fd4cfbfb7d7323d2151b0 -F www/pragma.tcl f954f5c5eb98b4ba33c09d4fd866600e78b0aacb +F www/pragma.tcl 5bac2d73a92136fb711d558003648383ec2b139b F www/quickstart.tcl 6f6f694b6139be2d967b1492eb9a6bdf7058aa60 F www/speed.tcl de99c82c4729a10b6733463636f15473c4ec95bc F www/sqlite.tcl b51fd15f0531a54874de785a9efba323eecd5975 @@ -255,7 +255,7 @@ F www/tclsqlite.tcl 560ecd6a916b320e59f2917317398f3d59b7cc25 F www/vdbe.tcl 095f106d93875c94b47367384ebc870517431618 F www/version3.tcl 092a01f5ef430d2c4acc0ae558d74c4bb89638a0 F www/whentouse.tcl fdacb0ba2d39831e8a6240d05a490026ad4c4e4c -P 0747b55882cf218c03b443e1eadec9eb19889554 -R b894ca6622f94383b4e07995b66df8ff +P c85f13f8f252faf423f12a3804f1fe2f950da660 +R d714e2a607a79ae47d80cca22b4581aa U danielk1977 -Z e7eb67c45eefd163ea64d3015b6203d0 +Z 9c7e9034616e577965e9472de918179e diff --git a/manifest.uuid b/manifest.uuid index 8685020387..99898f1036 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c85f13f8f252faf423f12a3804f1fe2f950da660 \ No newline at end of file +d28d1d68e5104726e6088361dfa7bf2cdd9985c7 \ No newline at end of file diff --git a/src/main.c b/src/main.c index dc17c224f9..bc882dce1b 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.263 2004/10/06 15:41:17 drh Exp $ +** $Id: main.c,v 1.264 2004/11/11 05:10:44 danielk1977 Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -202,7 +202,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ ** meta[2] Size of the page cache. ** meta[3] Use freelist if 0. Autovacuum if greater than zero. ** meta[4] Db text encoding. 1:UTF-8 3:UTF-16 LE 4:UTF-16 BE - ** meta[5] + ** meta[5] The user cookie. Used by the application. ** meta[6] ** meta[7] ** meta[8] diff --git a/src/pragma.c b/src/pragma.c index 190ef6a25e..fd6b6806da 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.75 2004/11/09 12:44:38 danielk1977 Exp $ +** $Id: pragma.c,v 1.76 2004/11/11 05:10:44 danielk1977 Exp $ */ #include "sqliteInt.h" #include @@ -724,6 +724,65 @@ void sqlite3Pragma( } } }else + /* + ** PRAGMA [database.]schema_cookie + ** PRAGMA [database.]schema_cookie = + ** + ** PRAGMA [database.]user_cookie + ** PRAGMA [database.]user_cookie = + ** + ** The pragma's schema_cookie and user_cookie are used to set or get + ** the value of the schema-cookie and user-cookie, respectively. Both + ** the schema-cookie and the user-cookie are 32-bit signed integers + ** stored in the database header. + ** + ** The schema-cookie is usually only manipulated internally by SQLite. It + ** is incremented by SQLite whenever the database schema is modified (by + ** creating or dropping a table or index). The schema cookie is used by + ** SQLite each time a query is executed to ensure that the internal cache + ** of the schema used when compiling the SQL query matches the schema of + ** the database against which the compiled query is actually executed. + ** Subverting this mechanism by using "PRAGMA schema_cookie" to modify + ** the schema-cookie is potentially dangerous and may lead to program + ** crashes or database corruption. Use with caution! + ** + ** The user-cookie is not used internally by SQLite. It may be used by + ** applications for any purpose. + */ + if( sqlite3StrICmp(zLeft, "schema_cookie")==0 || + sqlite3StrICmp(zLeft, "user_cookie")==0 ){ + + int iCookie; /* Cookie index. 0 for schema-cookie, 6 for user-cookie. */ + if( zLeft[0]=='s' || zLeft[0]=='S' ){ + iCookie = 0; + }else{ + iCookie = 5; + } + + if( zRight ){ + /* Write the specified cookie value */ + static const VdbeOpList setCookie[] = { + { OP_Transaction, 0, 1, 0}, /* 0 */ + { OP_Integer, 0, 0, 0}, /* 1 */ + { OP_SetCookie, 0, 0, 0}, /* 2 */ + }; + int addr = sqlite3VdbeAddOpList(v, ArraySize(setCookie), setCookie); + sqlite3VdbeChangeP1(v, addr, iDb); + sqlite3VdbeChangeP1(v, addr+1, atoi(zRight)); + sqlite3VdbeChangeP1(v, addr+2, iDb); + sqlite3VdbeChangeP2(v, addr+2, iCookie); + }else{ + /* Read the specified cookie value */ + static const VdbeOpList readCookie[] = { + { OP_ReadCookie, 0, 0, 0}, /* 0 */ + { OP_Callback, 1, 0, 0} + }; + int addr = sqlite3VdbeAddOpList(v, ArraySize(readCookie), readCookie); + sqlite3VdbeChangeP1(v, addr, iDb); + sqlite3VdbeChangeP2(v, addr, iCookie); + sqlite3VdbeSetNumCols(v, 1); + } + } #if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) /* diff --git a/test/pragma.test b/test/pragma.test index 1ab2214431..4eedfe33a8 100644 --- a/test/pragma.test +++ b/test/pragma.test @@ -12,7 +12,7 @@ # # This file implements tests for the PRAGMA command. # -# $Id: pragma.test,v 1.21 2004/11/04 14:47:13 drh Exp $ +# $Id: pragma.test,v 1.22 2004/11/11 05:10:44 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -367,5 +367,210 @@ do_test pragma-7.3 { } {main unlocked temp closed} +#---------------------------------------------------------------------- +# Test cases pragma-8.* test the "PRAGMA schema_cookie" and "PRAGMA +# user_cookie" statements. +# +# pragma-8.1: PRAGMA schema_cookie +# pragma-8.2: PRAGMA user_cookie +# + +# First check that we can set the schema cookie and then retrieve the +# same value. +do_test pragma-8.1.1 { + execsql { + PRAGMA schema_cookie = 105; + } +} {} +do_test pragma-8.1.2 { + execsql { + PRAGMA schema_cookie; + } +} 105 +do_test pragma-8.1.3 { + execsql { + PRAGMA schema_cookie = 106; + } +} {} +do_test pragma-8.1.4 { + execsql { + PRAGMA schema_cookie; + } +} 106 + +# Check that creating a table modifies the schema-cookie (this is really +# to verify that the value being read is in fact the schema cookie). +do_test pragma-8.1.5 { + execsql { + CREATE TABLE t4(a, b, c); + INSERT INTO t4 VALUES(1, 2, 3); + SELECT * FROM t4; + } +} {1 2 3} +do_test pragma-8.1.6 { + execsql { + PRAGMA schema_cookie; + } +} 107 + +# Now open a second connection to the database. Ensure that changing the +# schema-cookie using the first connection forces the second connection +# to reload the schema. This has to be done using the C-API test functions, +# because the TCL API accounts for SCHEMA_ERROR and retries the query. +do_test pragma-8.1.7 { + set ::DB2 [sqlite3 db2 test.db] + execsql { + SELECT * FROM t4; + } db2 +} {1 2 3} +do_test pragma-8.1.8 { + execsql { + PRAGMA schema_cookie = 108; + } +} {} +do_test pragma-8.1.9 { + set ::STMT [sqlite3_prepare $::DB2 "SELECT * FROM t4" -1 DUMMY] + sqlite3_step $::STMT +} SQLITE_ERROR +do_test pragma-8.1.10 { + sqlite3_finalize $::STMT +} SQLITE_SCHEMA + +# Make sure the schema-cookie can be manipulated in an attached database. +file delete -force test2.db +file delete -force test2.db-journal +do_test pragma-8.1.11 { + execsql { + ATTACH 'test2.db' AS aux; + CREATE TABLE aux.t1(a, b, c); + PRAGMA aux.schema_cookie = 205; + } +} {} +do_test pragma-8.1.12 { + execsql { + PRAGMA aux.schema_cookie; + } +} 205 +do_test pragma-8.1.13 { + execsql { + PRAGMA schema_cookie; + } +} 108 + +# And check that modifying the schema-cookie in an attached database +# forces the second connection to reload the schema. +do_test pragma-8.1.14 { + set ::DB2 [sqlite3 db2 test.db] + execsql { + ATTACH 'test2.db' AS aux; + SELECT * FROM aux.t1; + } db2 +} {} +do_test pragma-8.1.15 { + execsql { + PRAGMA aux.schema_cookie = 206; + } +} {} +do_test pragma-8.1.16 { + set ::STMT [sqlite3_prepare $::DB2 "SELECT * FROM aux.t1" -1 DUMMY] + sqlite3_step $::STMT +} SQLITE_ERROR +do_test pragma-8.1.17 { + sqlite3_finalize $::STMT +} SQLITE_SCHEMA +do_test pragma-8.1.18 { + db2 close +} {} + +# Now test that the user-cookie can be read and written (and that we aren't +# accidentally manipulating the schema-cookie instead). +do_test pragma-8.2.1 { + execsql { + PRAGMA user_cookie; + } +} {0} +do_test pragma-8.2.2 { + execsql { + PRAGMA user_cookie = 2; + } +} {} +do_test pragma-8.2.3 { + execsql { + PRAGMA user_cookie; + } +} {2} +do_test pragma-8.2.4 { + execsql { + PRAGMA schema_cookie; + } +} {108} + +# Check that the user-cookie in the auxilary database can be manipulated ( +# and that we aren't accidentally manipulating the same in the main db). +do_test pragma-8.2.5 { + execsql { + PRAGMA aux.user_cookie; + } +} {0} +do_test pragma-8.2.6 { + execsql { + PRAGMA aux.user_cookie = 3; + } +} {} +do_test pragma-8.2.7 { + execsql { + PRAGMA aux.user_cookie; + } +} {3} +do_test pragma-8.2.8 { + execsql { + PRAGMA main.user_cookie; + } +} {2} + +# Now check that a ROLLBACK resets the user-cookie if it has been modified +# within a transaction. +do_test pragma-8.2.9 { + execsql { + BEGIN; + PRAGMA aux.user_cookie = 10; + PRAGMA user_cookie = 11; + } +} {} +do_test pragma-8.2.10 { + execsql { + PRAGMA aux.user_cookie; + } +} {10} +do_test pragma-8.2.11 { + execsql { + PRAGMA main.user_cookie; + } +} {11} +do_test pragma-8.2.12 { + execsql { + ROLLBACK; + PRAGMA aux.user_cookie; + } +} {3} +do_test pragma-8.2.13 { + execsql { + PRAGMA main.user_cookie; + } +} {2} + +# Try a negative value for the user-cookie +do_test pragma-8.2.14 { + execsql { + PRAGMA user_cookie = -450; + } +} {} +do_test pragma-8.2.15 { + execsql { + PRAGMA user_cookie; + } +} {-450} finish_test + + diff --git a/www/pragma.tcl b/www/pragma.tcl index e1913c061d..525f6a0a8d 100644 --- a/www/pragma.tcl +++ b/www/pragma.tcl @@ -1,7 +1,7 @@ # # Run this Tcl script to generate the pragma.html file. # -set rcsid {$Id: pragma.tcl,v 1.1 2004/11/10 05:48:57 danielk1977 Exp $} +set rcsid {$Id: pragma.tcl,v 1.2 2004/11/11 05:10:44 danielk1977 Exp $} source common.tcl header {Pragma statements supported by SQLite} @@ -27,13 +27,15 @@ different in the following important respects: engine. -

The available pragma's fall into three basic categories:

+

The available pragmas fall into four basic categories:

@@ -56,7 +58,7 @@ treated as 1, and will not generate an error. When the value is returned it is as an integer.

} -Section {Pragmas used to modify library operation} modify +Section {Pragmas to modify library operation} modify puts {
    @@ -210,7 +212,7 @@ puts {
} -Section {Pragma's used to query the database schema} schema +Section {Pragmas to query the database schema} schema puts {
    @@ -247,7 +249,39 @@ puts {
} -Section {Pragma's used to debug the library} debug +Section {Pragmas to query/modify cookie values} cookie + +puts { + +
    +
  • PRAGMA [database.]schema_cookie; +
    PRAGMA [database.]schema_cookie =
    integer ; +
    PRAGMA [database.]user_cookie; +
    PRAGMA [database.]user_cookie =
    integer ; + + +

    The pragmas schema_cookie and user_cookie are used to set or get + the value of the schema-cookie and user-cookie, respectively. Both + the schema-cookie and the user-cookie are 32-bit signed integers + stored in the database header.

    + +

    The schema-cookie is usually only manipulated internally by SQLite. + It is incremented by SQLite whenever the database schema is modified + (by creating or dropping a table or index). The schema cookie is + used by SQLite each time a query is executed to ensure that the + internal cache of the schema used when compiling the SQL query matches + the schema of the database against which the compiled query is actually + executed. Subverting this mechanism by using "PRAGMA schema_cookie" + to modify the schema-cookie is potentially dangerous and may lead + to program crashes or database corruption. Use with caution!

    + +

    The user-cookie is not used internally by SQLite. It may be used by + applications for any purpose.

    +
  • +
+} + +Section {Pragmas to debug the library} debug puts {