From 4312db55d95877907bff257c95c41d463494de7c Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 3 Jun 2003 01:47:11 +0000 Subject: [PATCH] Additional testing of the ATTACH command with bug fixes for the new problems that the tests found. (CVS 998) FossilOrigin-Name: 3e8889d7ce5e99fc855526fc1bb62ddbe282bfc5 --- manifest | 22 +++++----- manifest.uuid | 2 +- src/attach.c | 8 ++-- src/sqliteInt.h | 4 +- src/trigger.c | 16 +++---- test/attach.test | 104 +++++++++++++++++++++++++++++++++++++++++++++- test/format3.test | 19 ++++++++- test/misc1.test | 21 +++++++++- 8 files changed, 168 insertions(+), 28 deletions(-) diff --git a/manifest b/manifest index cfd889ee0b..2492b32749 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C The\sOP_Checkpoint\sopcode\sis\snow\sa\sno-op\sif\sinvoked\son\sa\sdatabase\sthat\salready\nhas\san\sactive\scheckpoint\sjournal.\s\sTicket\s#333.\s(CVS\s997) -D 2003-06-02T23:14:13 +C Additional\stesting\sof\sthe\sATTACH\scommand\swith\sbug\sfixes\sfor\sthe\snew\sproblems\nthat\sthe\stests\sfound.\s(CVS\s998) +D 2003-06-03T01:47:11 F Makefile.in 1ff85c27d4350c74118341024e8a4fb2a04a3a43 F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906 F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd @@ -19,7 +19,7 @@ F publish.sh 86b5e8535830a2588f62ce1d5d1ef00e1dede23a F spec.template 238f7db425a78dc1bb7682e56e3834c7270a3f5e F sqlite.1 83f4a9d37bdf2b7ef079a82d54eaf2e3509ee6ea F sqlite.pc.in 30552343140c53304c2a658c080fbe810cd09ca2 -F src/attach.c 4f0aa5add0fb3c11b6a2130a1c8593bb5063b6d4 +F src/attach.c db89b086f58b679e3f140296e3b95942989b04ba F src/auth.c c8f50d4507e37779d96ff3c55417bc2b612dfed6 F src/btree.c 8092dca45dcdb69c61273db0213cbb85760673c7 F src/btree.h 9b7c09f1e64274d7bb74a57bbfc63778f67b1048 @@ -47,7 +47,7 @@ F src/select.c 76b3a5cda76421cfe82d6a96c72308c2518cb2f9 F src/shell.c b63089a91d6584df06eaa2e53ea1150c68ab1e61 F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e F src/sqlite.h.in eec06462cba262c0ee03f38462a18a4bc66dda4e -F src/sqliteInt.h 7562ea21beb84e4f90ea0e016b02945ac35350a9 +F src/sqliteInt.h d1d883d9116dadf63ffe1bafe17ba6455b7db59e F src/table.c 4301926464d88d2c2c7cd21c3360aa75bf068b95 F src/tclsqlite.c 9e25f98f1765afa0716144ef57abda75c88f688d F src/test1.c 4596acd9d9f2a49fda0160a8a6dee5bfc7c6c325 @@ -55,7 +55,7 @@ F src/test2.c 5014337d8576b731cce5b5a14bec4f0daf432700 F src/test3.c 30985ebdfaf3ee1462a9b0652d3efbdc8d9798f5 F src/threadtest.c d641a5219e718e18a1a80a50eb9bb549f451f42e F src/tokenize.c 2ba93fe10d5f57f0cc20b07417c3244a30c324b3 -F src/trigger.c 5caf7697e6cd4cfaf38d55bff31580f4124d836f +F src/trigger.c 6ff205aaac4869e402d9902e528e1d22a85de14c F src/update.c 24260b4fda00c9726d27699a0561d53c0dccc397 F src/util.c 18d16fa3171e34b6f6f73ef0c61e7d9b73b78826 F src/vacuum.c 0820984615786c9ccdaad8032a792309b354a8eb @@ -63,7 +63,7 @@ F src/vdbe.c 4170cba0a05da0a93dcd674859fc1ce18f3fb0a3 F src/vdbe.h 985c24f312d10f9ef8f9a8b8ea62fcdf68e82f21 F src/where.c 1e645d430cb4b347159c28c6085e9801160f2099 F test/all.test 569a92a8ee88f5300c057cc4a8f50fbbc69a3242 -F test/attach.test f050eebbb7e45c0796add92fa3f9154d68d7a01a +F test/attach.test 771334395ba0af08ec27b83f516978989e606e5a F test/auth.test dee78be1f4f920bd6b15c4c947ce4d01bfe2826d F test/bigfile.test 1cd8256d4619c39bea48147d344f348823e78678 F test/bigrow.test 8ab252dba108f12ad64e337b0f2ff31a807ac578 @@ -79,7 +79,7 @@ F test/copy.test c860847f1bd66175ef7cb724326a1700e0295820 F test/delete.test 1586a00574e699a9913bc3403261813e8a93e6b9 F test/expr.test 48bc6400627532ec97e233809e33d336468bc84c F test/fkey1.test d65c824459916249bee501532d6154ddab0b5db7 -F test/format3.test 64ab6c4db132b28a645996d413530f7b2a462cc2 +F test/format3.test b05cb2968841553698290f2833f72894f156024e F test/func.test 000515779001ac6899eec4b54e65c6e2501279d4 F test/in.test 22de8a3eb27265aab723adc513bea0e76bef70c6 F test/index.test 90ef4c426865f15937858bd433cc82b9c11af913 @@ -95,7 +95,7 @@ F test/malloc.test 7ba32a9ebd3aeed52ae4aaa6d42ca37e444536fd F test/memdb.test ab1d16eb3179272016b1fe5fa3988e9c2f6c5594 F test/memleak.test a18e6810cae96d2f6f5136920267adbefc8e1e90 F test/minmax.test b54ac3bc45460a4976b08ef363e05c032418726e -F test/misc1.test 865c907df58195364eaf2e69426e9674bc8d1a8c +F test/misc1.test c7dc2f2bd702d8283e885a64ec0714be26cfb051 F test/misuse.test a3aa2b18a97e4c409a1fcaff5151a4dd804a0162 F test/notnull.test 7a08117a71e74b0321aaa937dbeb41a09d6eb1d0 F test/null.test 5c2b57307e4b6178aae825eb65ddbee01e76b0fd @@ -165,7 +165,7 @@ F www/speed.tcl cb4c10a722614aea76d2c51f32ee43400d5951be F www/sqlite.tcl 4bd1729e320f5fa9125f0022b281fbe839192125 F www/tclsqlite.tcl 1db15abeb446aad0caf0b95b8b9579720e4ea331 F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218 -P 77ec13dab85b70795ef06ff2c714cca0cd496837 -R d450e05d46a3501d91726056bd4029e5 +P daf7b94017f03638da1ef65830f3762be030b93c +R 64dc9487d2ea82a1f70ee389c18ab473 U drh -Z ef7ae355ee25a92de1dd5e8db797cf3d +Z 95bab4cd51ed3d170690377c2faf1c26 diff --git a/manifest.uuid b/manifest.uuid index 71fdec59a1..d8d624a765 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -daf7b94017f03638da1ef65830f3762be030b93c \ No newline at end of file +3e8889d7ce5e99fc855526fc1bb62ddbe282bfc5 \ No newline at end of file diff --git a/src/attach.c b/src/attach.c index 77be3bcf98..d8901187be 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.4 2003/05/31 16:21:12 drh Exp $ +** $Id: attach.c,v 1.5 2003/06/03 01:47:11 drh Exp $ */ #include "sqliteInt.h" @@ -148,6 +148,7 @@ int sqliteFixInit( if( iDb<0 || iDb==1 ) return 0; db = pParse->db; assert( db->nDb>iDb ); + pFix->pParse = pParse; pFix->zDb = db->aDb[iDb].zName; pFix->zType = zType; pFix->pName = pName; @@ -182,8 +183,9 @@ int sqliteFixSrcList( pList->a[i].zDatabase = sqliteStrDup(zDb); }else if( sqliteStrICmp(pList->a[i].zDatabase,zDb)!=0 ){ sqliteErrorMsg(pFix->pParse, - "%s %.*s cannot reference objects in database %s", - pFix->zType, pFix->pName->n, pFix->pName->z, pList->a[i].zDatabase); + "%s %z cannot reference objects in database %s", + pFix->zType, sqliteStrNDup(pFix->pName->z, pFix->pName->n), + pList->a[i].zDatabase); return 1; } if( sqliteFixSelect(pFix, pList->a[i].pSelect) ) return 1; diff --git a/src/sqliteInt.h b/src/sqliteInt.h index e25145d2a2..4ab58d0cf5 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.190 2003/06/02 23:14:13 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.191 2003/06/03 01:47:11 drh Exp $ */ #include "config.h" #include "sqlite.h" @@ -904,7 +904,7 @@ struct Trigger { IdList *pColumns; /* If this is an UPDATE OF trigger, the is stored here */ int foreach; /* One of TK_ROW or TK_STATEMENT */ - Token *pNameToken; /* Token containing zName. Use during parsing only */ + Token nameToken; /* Token containing zName. Use during parsing only */ TriggerStep *step_list; /* Link list of trigger program steps */ Trigger *pNext; /* Next trigger associated with the table */ diff --git a/src/trigger.c b/src/trigger.c index eec48e0ffa..97891b2cb9 100644 --- a/src/trigger.c +++ b/src/trigger.c @@ -54,6 +54,7 @@ void sqliteBeginTrigger( char *zName = 0; /* Name of the trigger */ sqlite *db = pParse->db; int iDb; /* When database to store the trigger in */ + DbFixer sFix; /* Check that: ** 1. the trigger name does not already exist. @@ -64,12 +65,13 @@ void sqliteBeginTrigger( */ if( sqlite_malloc_failed ) goto trigger_cleanup; assert( pTableName->nSrc==1 ); - assert( pTableName->a[0].zDatabase==0 ); - if( pParse->initFlag ){ - pTableName->a[0].zDatabase = db->aDb[pParse->iDb].zName; + if( pParse->initFlag + && sqliteFixInit(&sFix, pParse, pParse->iDb, "trigger", pName) + && sqliteFixSrcList(&sFix, pTableName) + ){ + goto trigger_cleanup; } tab = sqliteSrcListLookup(pParse, pTableName); - pTableName->a[0].zDatabase = 0; if( !tab ){ goto trigger_cleanup; } @@ -138,7 +140,7 @@ void sqliteBeginTrigger( nt->pWhen = sqliteExprDup(pWhen); nt->pColumns = sqliteIdListDup(pColumns); nt->foreach = foreach; - nt->pNameToken = pName; + sqliteTokenCopy(&nt->nameToken,pName); assert( pParse->pNewTrigger==0 ); pParse->pNewTrigger = nt; @@ -170,11 +172,10 @@ void sqliteFinishTrigger( pStepList->pTrig = nt; pStepList = pStepList->pNext; } - if( sqliteFixInit(&sFix, pParse, nt->iDb, "trigger", nt->pNameToken) + if( sqliteFixInit(&sFix, pParse, nt->iDb, "trigger", &nt->nameToken) && sqliteFixTriggerStep(&sFix, nt->step_list) ){ goto triggerfinish_cleanup; } - nt->pNameToken = 0; /* if we are not initializing, and this trigger is not on a TEMP table, ** build the sqlite_master entry @@ -366,6 +367,7 @@ void sqliteDeleteTrigger(Trigger *pTrigger){ sqliteFree(pTrigger->table); sqliteExprDelete(pTrigger->pWhen); sqliteIdListDelete(pTrigger->pColumns); + if( pTrigger->nameToken.dyn ) sqliteFree((char*)pTrigger->nameToken.z); sqliteFree(pTrigger); } diff --git a/test/attach.test b/test/attach.test index 27b1a07469..f3ca1881a9 100644 --- a/test/attach.test +++ b/test/attach.test @@ -12,7 +12,7 @@ # focus of this script is testing the ATTACH and DETACH commands # and related functionality. # -# $Id: attach.test,v 1.6 2003/05/31 16:21:13 drh Exp $ +# $Id: attach.test,v 1.7 2003/06/03 01:47:12 drh Exp $ # set testdir [file dirname $argv0] @@ -469,10 +469,112 @@ do_test attach-4.13 { } } {910 1112 1516} +# Tests for the sqliteFix...() routines in attach.c +# +do_test attach-5.1 { + db close + sqlite db test.db + file delete -force test2.db + sqlite db2 test2.db + catchsql { + ATTACH DATABASE 'test.db' AS orig; + CREATE TRIGGER r1 AFTER INSERT ON orig.t1 BEGIN; + SELECT 'no-op'; + END; + } db2 +} {1 {triggers may not be added to auxiliary database orig}} +do_test attach-5.2 { + catchsql { + CREATE TABLE t5(x,y); + CREATE TRIGGER r5 AFTER INSERT ON t5 BEGIN + SELECT 'no-op'; + END; + } db2 +} {0 {}} +do_test attach-5.3 { + catchsql { + DROP TRIGGER r5; + CREATE TRIGGER r5 AFTER INSERT ON t5 BEGIN + SELECT 'no-op' FROM orig.t1; + END; + } db2 +} {1 {trigger r5 cannot reference objects in database orig}} +do_test attach-5.4 { + catchsql { + CREATE TEMP TABLE t6(p,q,r); + CREATE TRIGGER r5 AFTER INSERT ON t5 BEGIN + SELECT 'no-op' FROM temp.t6; + END; + } db2 +} {1 {trigger r5 cannot reference objects in database temp}} +do_test attach-5.5 { + catchsql { + CREATE TRIGGER r5 AFTER INSERT ON t5 BEGIN + SELECT 'no-op' || (SELECT * FROM temp.t6); + END; + } db2 +} {1 {trigger r5 cannot reference objects in database temp}} +do_test attach-5.6 { + catchsql { + CREATE TRIGGER r5 AFTER INSERT ON t5 BEGIN + SELECT 'no-op' FROM t1 WHERE x<(SELECT min(x) FROM temp.t6); + END; + } db2 +} {1 {trigger r5 cannot reference objects in database temp}} +do_test attach-5.7 { + catchsql { + CREATE TRIGGER r5 AFTER INSERT ON t5 BEGIN + SELECT 'no-op' FROM t1 GROUP BY 1 HAVING x<(SELECT min(x) FROM temp.t6); + END; + } db2 +} {1 {trigger r5 cannot reference objects in database temp}} +do_test attach-5.7 { + catchsql { + CREATE TRIGGER r5 AFTER INSERT ON t5 BEGIN + SELECT max(1,x,(SELECT min(x) FROM temp.t6)) FROM t1; + END; + } db2 +} {1 {trigger r5 cannot reference objects in database temp}} +do_test attach-5.8 { + catchsql { + CREATE TRIGGER r5 AFTER INSERT ON t5 BEGIN + INSERT INTO t1 VALUES((SELECT min(x) FROM temp.t6),5); + END; + } db2 +} {1 {trigger r5 cannot reference objects in database temp}} +do_test attach-5.9 { + catchsql { + CREATE TRIGGER r5 AFTER INSERT ON t5 BEGIN + DELETE FROM t1 WHERE x<(SELECT min(x) FROM temp.t6); + END; + } db2 +} {1 {trigger r5 cannot reference objects in database temp}} + +# Check to make sure we get a sensible error if unable to open +# the file that we are trying to attach. +# +do_test attach-6.1 { + catchsql { + ATTACH DATABASE 'no-such-file' AS nosuch; + } +} {1 {cannot attach empty database: nosuch}} +file delete -force no-such-file +do_test attach-6.2 { + sqlite dbx cannot-read + dbx eval {CREATE TABLE t1(a,b,c)} + dbx close + catch {file attributes cannot-read -permission 0000} + catch {file attributes cannot-read -readonly 1} + catchsql { + ATTACH DATABASE 'cannot-read' AS noread; + } +} {1 {unable to open database: cannot-read}} +file delete -force cannot-read for {set i 2} {$i<=15} {incr i} { catch {db$i close} } +file delete -force test2.db finish_test diff --git a/test/format3.test b/test/format3.test index 04bec60d91..41db94da29 100644 --- a/test/format3.test +++ b/test/format3.test @@ -12,7 +12,7 @@ # focus of this file is testing the the library is able to correctly # handle file-format 3 (version 2.6.x) databases. # -# $Id: format3.test,v 1.2 2002/12/04 21:50:16 drh Exp $ +# $Id: format3.test,v 1.3 2003/06/03 01:47:12 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -718,4 +718,21 @@ do_test format3-11.7 { } } {0 0} +# Make sure attempts to attach a format 3 database fail. +# +do_test format3-12.1 { + file delete -force test2.db + sqlite db2 test2.db + catchsql { + CREATE TABLE t8(x,y); + ATTACH DATABASE 'test.db' AS format3; + } db2; +} {1 {incompatible file format in auxiliary database: format3}} +do_test format3-12.2 { + catchsql { + ATTACH DATABASE 'test2.db' AS test2; + } +} {1 {cannot attach auxiliary databases to an older format master database}} +db2 close + finish_test diff --git a/test/misc1.test b/test/misc1.test index cf14021897..d2f1b7a7e9 100644 --- a/test/misc1.test +++ b/test/misc1.test @@ -13,7 +13,7 @@ # This file implements tests for miscellanous features that were # left out of other test files. # -# $Id: misc1.test,v 1.21 2003/02/26 13:52:52 drh Exp $ +# $Id: misc1.test,v 1.22 2003/06/03 01:47:12 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -518,6 +518,23 @@ do_test misc1-16.6 { } } {1 1 5 5 6 6} - +# Ticket #333: Temp triggers that modify persistent tables. +# +do_test misc1-17.1 { + execsql { + BEGIN; + CREATE TABLE RealTable(TestID INTEGER PRIMARY KEY, TestString TEXT); + CREATE TEMP TABLE TempTable(TestID INTEGER PRIMARY KEY, TestString TEXT); + CREATE TEMP TRIGGER trigTest_1 AFTER UPDATE ON TempTable BEGIN + INSERT INTO RealTable(TestString) + SELECT new.TestString FROM TempTable LIMIT 1; + END; + INSERT INTO TempTable(TestString) VALUES ('1'); + INSERT INTO TempTable(TestString) VALUES ('2'); + UPDATE TempTable SET TestString = TestString + 1 WHERE TestID IN (1, 2); + COMMIT; + SELECT TestString FROM RealTable ORDER BY 1; + } +} {2 3} finish_test