]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Backport of (1628) to version 2. (CVS 1631)
authordanielk1977 <danielk1977@noemail.net>
Sat, 19 Jun 2004 04:23:25 +0000 (04:23 +0000)
committerdanielk1977 <danielk1977@noemail.net>
Sat, 19 Jun 2004 04:23:25 +0000 (04:23 +0000)
FossilOrigin-Name: cce250eaee59eac2d15437b564f049c5b241317c

manifest
manifest.uuid
src/main.c
test/trigger1.test

index 8e9840825ba680841f04c226a78e2ab17fb9a408..59593a8a38c6f83dc2a7fd97258848f64cf3edfc 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Update\sthe\spublish.sh\sscript\sso\sthat\sit\sno\slonger\sgenerates\sdocumentation\npages\s(that\sis\shandled\sby\sthe\sversion\s3.0.0\spublish.sh).\s\sAlso\sinsert\nversion\snumbers\sin\sthe\sfilenames\sof\sall\sbuild\sproducts.\s(CVS\s1601)
-D 2004-06-16T01:21:01
+C Backport\sof\s(1628)\sto\sversion\s2.\s(CVS\s1631)
+D 2004-06-19T04:23:25
 F Makefile.in ab7b0d5118e2da97bac66be8684a1034e3500f5a
 F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
 F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
@@ -36,7 +36,7 @@ F src/func.c 34fead7a33e82095f6412d3fafd379d47864b3be
 F src/hash.c 9b56ef3b291e25168f630d5643a4264ec011c70e
 F src/hash.h 3247573ab95b9dd90bcca0307a75d9a16da1ccc7
 F src/insert.c c0485ee2d1b99322894e2d1e0b576fd05ed75616
-F src/main.c 94dd355768e2a389e184a069b6880f4bac100307
+F src/main.c 35b6917da56ff1abdfab7fc53d10b815dd4cac16
 F src/md5.c fe4f9c9c6f71dfc26af8da63e4d04489b1430565
 F src/os.c edcd42ad1cf13e7322f814c50a3e6eb09d3915bb
 F src/os.h 250a3789be609adfee5c5aa20137ce8683276f24
@@ -138,7 +138,7 @@ F test/thread1.test 53f050d5be6932d9430df7756edd379366508ff6
 F test/threadtest1.c f7f896e62ed46feae1dc411114a48c15a0f82ee2
 F test/threadtest2.c d94ca4114fd1504f7e0ae724bcd83d4b40931d86
 F test/trans.test 0cb8256daff1ae0da75321e00125338c6681158d
-F test/trigger1.test 4538c1c7d6bbca5dfe619ea6e1682b07ece95b21
+F test/trigger1.test cf8c8bbdaa254b000242f89e024f9b44cafda093
 F test/trigger2.test 0767ab30cb5a2c8402c8524f3d566b410b6f5263
 F test/trigger3.test a95ccace88291449f5eae7139ec438a42f90654d
 F test/trigger4.test 542afce45774e8f8e1130b96b8675f414d6e4bd8
@@ -188,7 +188,7 @@ F www/sqlite.tcl 3c83b08cf9f18aa2d69453ff441a36c40e431604
 F www/tclsqlite.tcl b9271d44dcf147a93c98f8ecf28c927307abd6da
 F www/vdbe.tcl 9b9095d4495f37697fd1935d10e14c6015e80aa1
 F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4
-P 24adf9ed5988d6e110a750f75b767fad163689c6
-R bad18b9b4e0f573517fda2790c833ba9
-U drh
-Z 8af7b97de359371eafa7d3ea06076f21
+P f2b8d35825a2137e83419e9aebc9619a9db2ada8
+R 08b10f88d920f85f8c5d79ea0011a791
+U danielk1977
+Z 231032d5f4f2d83a2985bd8df240fe0c
index b6be415622829a08377bcd2ab4fe7c84bc21b508..87b2667aa4c81bfa011da81929c4a5966d5f9fce 100644 (file)
@@ -1 +1 @@
-f2b8d35825a2137e83419e9aebc9619a9db2ada8
\ No newline at end of file
+cce250eaee59eac2d15437b564f049c5b241317c
\ No newline at end of file
index 27f237f7c10432e311a941b0a807227055548bb0..25d0f9b3d1abf95fbdc07bd1db6f25909e09386d 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.164 2004/04/23 17:04:45 drh Exp $
+** $Id: main.c,v 1.164.2.1 2004/06/19 04:23:25 danielk1977 Exp $
 */
 #include "sqliteInt.h"
 #include "os.h"
@@ -189,10 +189,13 @@ static int sqliteInitOne(sqlite *db, int iDb, char **pzErrMsg){
   BtCursor *curMain;
   int size;
   Table *pTab;
-  char *azArg[6];
+  char const *azArg[6];
   char zDbNum[30];
   int meta[SQLITE_N_BTREE_META];
   InitData initData;
+  char const *zMasterSchema;
+  char const *zMasterName;
+  char *zSql = 0;
 
   /*
   ** The master database table has a structure like this
@@ -216,62 +219,38 @@ static int sqliteInitOne(sqlite *db, int iDb, char **pzErrMsg){
      ")"
   ;
 
-  /* The following SQL will read the schema from the master tables.
-  ** The first version works with SQLite file formats 2 or greater.
-  ** The second version is for format 1 files.
-  **
-  ** Beginning with file format 2, the rowid for new table entries
-  ** (including entries in sqlite_master) is an increasing integer.
-  ** So for file format 2 and later, we can play back sqlite_master
-  ** and all the CREATE statements will appear in the right order.
-  ** But with file format 1, table entries were random and so we
-  ** have to make sure the CREATE TABLEs occur before their corresponding
-  ** CREATE INDEXs.  (We don't have to deal with CREATE VIEW or
-  ** CREATE TRIGGER in file format 1 because those constructs did
-  ** not exist then.) 
+  assert( iDb>=0 && iDb<db->nDb );
+
+  /* zMasterSchema and zInitScript are set to point at the master schema
+  ** and initialisation script appropriate for the database being
+  ** initialised. zMasterName is the name of the master table.
   */
-  static char init_script[] = 
-     "SELECT type, name, rootpage, sql, 1 FROM sqlite_temp_master "
-     "UNION ALL "
-     "SELECT type, name, rootpage, sql, 0 FROM sqlite_master";
-  static char older_init_script[] = 
-     "SELECT type, name, rootpage, sql, 1 FROM sqlite_temp_master "
-     "UNION ALL "
-     "SELECT type, name, rootpage, sql, 0 FROM sqlite_master "
-     "WHERE type='table' "
-     "UNION ALL "
-     "SELECT type, name, rootpage, sql, 0 FROM sqlite_master "
-     "WHERE type='index'";
-
-
-  assert( iDb>=0 && iDb!=1 && iDb<db->nDb );
-
-  /* Construct the schema tables: sqlite_master and sqlite_temp_master
+  if( iDb==1 ){
+    zMasterSchema = temp_master_schema;
+    zMasterName = TEMP_MASTER_NAME;
+  }else{
+    zMasterSchema = master_schema;
+    zMasterName = MASTER_NAME;
+  }
+
+  /* Construct the schema table.
   */
   sqliteSafetyOff(db);
   azArg[0] = "table";
-  azArg[1] = MASTER_NAME;
+  azArg[1] = zMasterName;
   azArg[2] = "2";
-  azArg[3] = master_schema;
+  azArg[3] = zMasterSchema;
   sprintf(zDbNum, "%d", iDb);
   azArg[4] = zDbNum;
   azArg[5] = 0;
   initData.db = db;
   initData.pzErrMsg = pzErrMsg;
-  sqliteInitCallback(&initData, 5, azArg, 0);
-  pTab = sqliteFindTable(db, MASTER_NAME, "main");
+  sqliteInitCallback(&initData, 5, (char **)azArg, 0);
+  pTab = sqliteFindTable(db, zMasterName, db->aDb[iDb].zName);
   if( pTab ){
     pTab->readOnly = 1;
-  }
-  if( iDb==0 ){
-    azArg[1] = TEMP_MASTER_NAME;
-    azArg[3] = temp_master_schema;
-    azArg[4] = "1";
-    sqliteInitCallback(&initData, 5, azArg, 0);
-    pTab = sqliteFindTable(db, TEMP_MASTER_NAME, "temp");
-    if( pTab ){
-      pTab->readOnly = 1;
-    }
+  }else{
+    return SQLITE_NOMEM;
   }
   sqliteSafetyOn(db);
 
@@ -320,7 +299,7 @@ static int sqliteInitOne(sqlite *db, int iDb, char **pzErrMsg){
       sqliteSetString(pzErrMsg, "unsupported file format", (char*)0);
       return SQLITE_ERROR;
     }
-  }else if( db->file_format!=meta[2] || db->file_format<4 ){
+  }else if( iDb!=1 && (db->file_format!=meta[2] || db->file_format<4) ){
     assert( db->file_format>=4 );
     if( meta[2]==0 ){
       sqliteSetString(pzErrMsg, "cannot attach empty database: ",
@@ -340,18 +319,35 @@ static int sqliteInitOne(sqlite *db, int iDb, char **pzErrMsg){
   */
   assert( db->init.busy );
   sqliteSafetyOff(db);
-  if( iDb==0 ){
-    rc = sqlite_exec(db, 
-        db->file_format>=2 ? init_script : older_init_script,
-        sqliteInitCallback, &initData, 0);
+
+  /* The following SQL will read the schema from the master tables.
+  ** The first version works with SQLite file formats 2 or greater.
+  ** The second version is for format 1 files.
+  **
+  ** Beginning with file format 2, the rowid for new table entries
+  ** (including entries in sqlite_master) is an increasing integer.
+  ** So for file format 2 and later, we can play back sqlite_master
+  ** and all the CREATE statements will appear in the right order.
+  ** But with file format 1, table entries were random and so we
+  ** have to make sure the CREATE TABLEs occur before their corresponding
+  ** CREATE INDEXs.  (We don't have to deal with CREATE VIEW or
+  ** CREATE TRIGGER in file format 1 because those constructs did
+  ** not exist then.) 
+  */
+  if( db->file_format>=2 ){
+    sqliteSetString(&zSql, 
+        "SELECT type, name, rootpage, sql, ", zDbNum, " FROM \"",
+       db->aDb[iDb].zName, "\".", zMasterName, (char*)0);
   }else{
-    char *zSql = 0;
     sqliteSetString(&zSql, 
-       "SELECT type, name, rootpage, sql, ", zDbNum, " FROM \"",
-       db->aDb[iDb].zName, "\".sqlite_master", (char*)0);
-    rc = sqlite_exec(db, zSql, sqliteInitCallback, &initData, 0);
-    sqliteFree(zSql);
+        "SELECT type, name, rootpage, sql, ", zDbNum, " FROM \"",
+       db->aDb[iDb].zName, "\".", zMasterName, 
+       " WHERE type IN ('table', 'index')"
+       " ORDER BY CASE type WHEN 'table' THEN 0 ELSE 1 END", (char*)0);
   }
+  rc = sqlite_exec(db, zSql, sqliteInitCallback, &initData, 0);
+
+  sqliteFree(zSql);
   sqliteSafetyOn(db);
   sqliteBtreeCloseCursor(curMain);
   if( sqlite_malloc_failed ){
@@ -361,9 +357,6 @@ static int sqliteInitOne(sqlite *db, int iDb, char **pzErrMsg){
   }
   if( rc==SQLITE_OK ){
     DbSetProperty(db, iDb, DB_SchemaLoaded);
-    if( iDb==0 ){
-      DbSetProperty(db, 1, DB_SchemaLoaded);
-    }
   }else{
     sqliteResetInternalSchema(db, iDb);
   }
@@ -391,13 +384,24 @@ int sqliteInit(sqlite *db, char **pzErrMsg){
   rc = SQLITE_OK;
   db->init.busy = 1;
   for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
-    if( DbHasProperty(db, i, DB_SchemaLoaded) ) continue;
-    assert( i!=1 );  /* Should have been initialized together with 0 */
+    if( DbHasProperty(db, i, DB_SchemaLoaded) || i==1 ) continue;
     rc = sqliteInitOne(db, i, pzErrMsg);
     if( rc ){
       sqliteResetInternalSchema(db, i);
     }
   }
+
+  /* Once all the other databases have been initialised, load the schema
+  ** for the TEMP database. This is loaded last, as the TEMP database
+  ** schema may contain references to objects in other databases.
+  */
+  if( rc==SQLITE_OK && db->nDb>1 && !DbHasProperty(db, 1, DB_SchemaLoaded) ){
+    rc = sqliteInitOne(db, 1, pzErrMsg);
+    if( rc ){
+      sqliteResetInternalSchema(db, 1);
+    }
+  }
+
   db->init.busy = 0;
   if( rc==SQLITE_OK ){
     db->flags |= SQLITE_Initialized;
index b55ca12378c9afa11a87e9f010aafed8f07b64a0..d8d08dec7b13f65323eb6b46607d9d3ec9d5b999 100644 (file)
@@ -412,5 +412,108 @@ do_test trigger-9.2 {
   }
 } {1 2 1 3 99 99 1 3}
 
+execsql {
+  DROP TABLE t2;
+  DROP TABLE t3;
+  DROP TABLE t4;
+}
+
+# Ticket #764. At one stage TEMP triggers would fail to re-install when the
+# schema was reloaded. The following tests ensure that TEMP triggers are
+# correctly re-installed.
+#
+# Also verify that references within trigger programs are resolved at
+# statement compile time, not trigger installation time. This means, for
+# example, that you can drop and re-create tables referenced by triggers. 
+do_test trigger-10.0 {
+  file delete -force test2.db
+  file delete -force test2.db-journal
+  sqlite db2 test2.db
+  execsql {CREATE TABLE t3(a, b, c);} db2
+  db2 close
+  execsql {
+    ATTACH 'test2.db' AS aux;
+  }
+} {}
+do_test trigger-10.1 {
+  execsql {
+    CREATE TABLE t1(a, b, c);
+    CREATE temp TABLE t2(a, b, c);
+    CREATE TABLE insert_log(db, a, b, c);
+  }
+} {}
+do_test trigger-10.2 {
+  execsql {
+    CREATE TEMP TRIGGER trig1 AFTER INSERT ON t1 BEGIN 
+      INSERT INTO insert_log VALUES('main', new.a, new.b, new.c);
+    END;
+    CREATE TEMP TRIGGER trig2 AFTER INSERT ON t2 BEGIN 
+      INSERT INTO insert_log VALUES('temp', new.a, new.b, new.c);
+    END;
+    CREATE TEMP TRIGGER trig3 AFTER INSERT ON t3 BEGIN 
+      INSERT INTO insert_log VALUES('aux', new.a, new.b, new.c);
+    END;
+  }
+} {}
+do_test trigger-10.3 {
+  execsql {
+    INSERT INTO t1 VALUES(1, 2, 3);
+    INSERT INTO t2 VALUES(4, 5, 6);
+    INSERT INTO t3  VALUES(7, 8, 9);
+  }
+} {}
+do_test trigger-10.4 {
+  execsql {
+    SELECT * FROM insert_log;
+  }
+} {main 1 2 3 temp 4 5 6 aux 7 8 9}
+do_test trigger-10.5 {
+  execsql {
+    BEGIN;
+    INSERT INTO t1 VALUES(1, 2, 3);
+    INSERT INTO t2 VALUES(4, 5, 6);
+    INSERT INTO t3  VALUES(7, 8, 9);
+    ROLLBACK;
+  }
+} {}
+do_test trigger-10.6 {
+  execsql {
+    SELECT * FROM insert_log;
+  }
+} {main 1 2 3 temp 4 5 6 aux 7 8 9}
+do_test trigger-10.7 {
+  execsql {
+    DELETE FROM insert_log;
+    INSERT INTO t1 VALUES(11, 12, 13);
+    INSERT INTO t2 VALUES(14, 15, 16);
+    INSERT INTO t3 VALUES(17, 18, 19);
+  }
+} {}
+do_test trigger-10.8 {
+  execsql {
+    SELECT * FROM insert_log;
+  }
+} {main 11 12 13 temp 14 15 16 aux 17 18 19}
+do_test trigger-10.8 {
+# Drop and re-create the insert_log table in a different database. Note
+# that we can change the column names because the trigger programs don't
+# use them explicitly.
+  execsql {
+    DROP TABLE insert_log;
+    CREATE temp TABLE insert_log(db, d, e, f);
+  }
+} {}
+do_test trigger-10.10 {
+  execsql {
+    INSERT INTO t1 VALUES(21, 22, 23);
+    INSERT INTO t2 VALUES(24, 25, 26);
+    INSERT INTO t3  VALUES(27, 28, 29);
+  }
+} {}
+do_test trigger-10.11 {
+  execsql {
+    SELECT * FROM insert_log;
+  }
+} {main 21 22 23 temp 24 25 26 aux 27 28 29}
 
 finish_test