]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add the schema_cookie and user_cookie pragmas. (CVS 2089)
authordanielk1977 <danielk1977@noemail.net>
Thu, 11 Nov 2004 05:10:43 +0000 (05:10 +0000)
committerdanielk1977 <danielk1977@noemail.net>
Thu, 11 Nov 2004 05:10:43 +0000 (05:10 +0000)
FossilOrigin-Name: d28d1d68e5104726e6088361dfa7bf2cdd9985c7

manifest
manifest.uuid
src/main.c
src/pragma.c
test/pragma.test
www/pragma.tcl

index 4d50a48a0b4ae5dda2cb36b499785d3948e02835..177395408abad648845d9deaa299e30aa8cd9bf8 100644 (file)
--- 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
index 86850203870b94c418af5dce02f49e7e8ce68392..99898f1036275c19174515a7f6eee0b7e839ef55 100644 (file)
@@ -1 +1 @@
-c85f13f8f252faf423f12a3804f1fe2f950da660
\ No newline at end of file
+d28d1d68e5104726e6088361dfa7bf2cdd9985c7
\ No newline at end of file
index dc17c224f917cbfe12868a49f617f0d9dc9541a3..bc882dce1b6783652f4f5e14821929baaf4e1396 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.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]
index 190ef6a25e6115942538d64cc325e99a37b5e656..fd6b6806da34785f25652d666922f1430d7493b5 100644 (file)
@@ -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 <ctype.h>
@@ -724,6 +724,65 @@ void sqlite3Pragma(
       }
     }
   }else
+  /*
+  **   PRAGMA [database.]schema_cookie
+  **   PRAGMA [database.]schema_cookie = <integer>
+  **
+  **   PRAGMA [database.]user_cookie
+  **   PRAGMA [database.]user_cookie = <integer>
+  **
+  ** 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)
   /*
index 1ab22144317bc5774e742bcd1420a80efdb85fc4..4eedfe33a873e91d2bdd3ce35029e469d3a0036b 100644 (file)
@@ -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
+
+
index e1913c061df3d8e5b1c1cc8dee5fd0a59a1d2bc1..525f6a0a8d7438b5cb4e762ec1525562fb7c8cd4 100644 (file)
@@ -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.
 </ul>
 
-<p>The available pragma's fall into three basic categories:</p>
+<p>The available pragmas fall into four basic categories:</p>
 <ul>
 <li>Pragmas used to <a href="#schema">query the schema</a> of the current 
     database.
 <li>Pragmas used to <a href="#modify">modify the operation</a> of the 
     SQLite library in some manner, or to query for the current mode of 
     operation.
+<li>Pragmas used to <a href="#cookie">query or modify the databases two 
+    cookie values</a>, the schema-cookie and the user-cookie.
 <li>Pragmas used to <a href="#debug">debug the library</a> and verify that
     database files are not corrupted.
 </ul>
@@ -56,7 +58,7 @@ treated as <b>1</b>, and will not generate an error.  When the <i>value</i>
 is returned it is as an integer.</p>
 }
 
-Section {Pragmas used to modify library operation} modify
+Section {Pragmas to modify library operation} modify
 
 puts {
 <ul>
@@ -210,7 +212,7 @@ puts {
 </ul>
 }
 
-Section {Pragma's used to query the database schema} schema
+Section {Pragmas to query the database schema} schema
 
 puts {
 <ul>
@@ -247,7 +249,39 @@ puts {
 </ul>
 }
 
-Section {Pragma's used to debug the library} debug
+Section {Pragmas to query/modify cookie values} cookie
+
+puts {
+
+<ul>
+<li><p><b>PRAGMA [database.]schema_cookie; 
+       <br>PRAGMA [database.]schema_cookie = </b><i>integer </i><b>;
+       <br>PRAGMA [database.]user_cookie;
+       <br>PRAGMA [database.]user_cookie = </b><i>integer </i><b>;</b>
+
+  
+<p>    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.</p>
+  
+<p>    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!</p>
+  
+<p>    The user-cookie is not used internally by SQLite. It may be used by
+       applications for any purpose.</p>
+</li>
+</ul>
+}
+
+Section {Pragmas to debug the library} debug
 
 puts {
 <ul>