-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
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
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
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
** 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"
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
")"
;
- /* 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);
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: ",
*/
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 ){
}
if( rc==SQLITE_OK ){
DbSetProperty(db, iDb, DB_SchemaLoaded);
- if( iDb==0 ){
- DbSetProperty(db, 1, DB_SchemaLoaded);
- }
}else{
sqliteResetInternalSchema(db, iDb);
}
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;
}
} {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